gicv3_main.c 13.1 KB
Newer Older
1
/*
2
 * Copyright (c) 2015-2017, 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
10
11
12
13
 */

#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <gicv3.h>
#include "gicv3_private.h"

14
const gicv3_driver_data_t *gicv3_driver_data;
15
16
static unsigned int gicv2_compat;

17
18
19
20
21
22
23
/*
 * Redistributor power operations are weakly bound so that they can be
 * overridden
 */
#pragma weak gicv3_rdistif_off
#pragma weak gicv3_rdistif_on

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*******************************************************************************
 * This function initialises the ARM GICv3 driver in EL3 with provided platform
 * inputs.
 ******************************************************************************/
void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data)
{
	unsigned int gic_version;

	assert(plat_driver_data);
	assert(plat_driver_data->gicd_base);
	assert(plat_driver_data->gicr_base);
	assert(plat_driver_data->rdistif_num);
	assert(plat_driver_data->rdistif_base_addrs);

	assert(IS_IN_EL3());

	/*
	 * The platform should provide a list of at least one type of
	 * interrupts
	 */
	assert(plat_driver_data->g0_interrupt_array ||
	       plat_driver_data->g1s_interrupt_array);

	/*
	 * If there are no interrupts of a particular type, then the number of
	 * interrupts of that type should be 0 and vice-versa.
	 */
	assert(plat_driver_data->g0_interrupt_array ?
	       plat_driver_data->g0_interrupt_num :
	       plat_driver_data->g0_interrupt_num == 0);
	assert(plat_driver_data->g1s_interrupt_array ?
	       plat_driver_data->g1s_interrupt_num :
	       plat_driver_data->g1s_interrupt_num == 0);

	/* Check for system register support */
59
60
61
#ifdef AARCH32
	assert(read_id_pfr1() & (ID_PFR1_GIC_MASK << ID_PFR1_GIC_SHIFT));
#else
62
63
	assert(read_id_aa64pfr0_el1() &
			(ID_AA64PFR0_GIC_MASK << ID_AA64PFR0_GIC_SHIFT));
64
#endif /* AARCH32 */
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

	/* The GIC version should be 3.0 */
	gic_version = gicd_read_pidr2(plat_driver_data->gicd_base);
	gic_version >>=	PIDR2_ARCH_REV_SHIFT;
	gic_version &= PIDR2_ARCH_REV_MASK;
	assert(gic_version == ARCH_REV_GICV3);

	/*
	 * Find out whether the GIC supports the GICv2 compatibility mode. The
	 * ARE_S bit resets to 0 if supported
	 */
	gicv2_compat = gicd_read_ctlr(plat_driver_data->gicd_base);
	gicv2_compat >>= CTLR_ARE_S_SHIFT;
	gicv2_compat = !(gicv2_compat & CTLR_ARE_S_MASK);

	/*
	 * Find the base address of each implemented Redistributor interface.
	 * The number of interfaces should be equal to the number of CPUs in the
	 * system. The memory for saving these addresses has to be allocated by
	 * the platform port
	 */
	gicv3_rdistif_base_addrs_probe(plat_driver_data->rdistif_base_addrs,
					   plat_driver_data->rdistif_num,
					   plat_driver_data->gicr_base,
					   plat_driver_data->mpidr_to_core_pos);

91
	gicv3_driver_data = plat_driver_data;
92

93
94
95
96
	/*
	 * The GIC driver data is initialized by the primary CPU with caches
	 * enabled. When the secondary CPU boots up, it initializes the
	 * GICC/GICR interface with the caches disabled. Hence flush the
97
	 * driver data to ensure coherency. This is not required if the
98
99
100
	 * platform has HW_ASSISTED_COHERENCY enabled.
	 */
#if !HW_ASSISTED_COHERENCY
101
102
103
104
	flush_dcache_range((uintptr_t) &gicv3_driver_data,
			sizeof(gicv3_driver_data));
	flush_dcache_range((uintptr_t) gicv3_driver_data,
			sizeof(*gicv3_driver_data));
105
106
#endif

107
108
109
110
111
112
113
114
115
116
117
	INFO("GICv3 %s legacy support detected."
			" ARM GICV3 driver initialized in EL3\n",
			gicv2_compat ? "with" : "without");
}

/*******************************************************************************
 * This function initialises the GIC distributor interface based upon the data
 * provided by the platform while initialising the driver.
 ******************************************************************************/
void gicv3_distif_init(void)
{
118
119
	unsigned int bitmap = 0;

120
121
122
123
	assert(gicv3_driver_data);
	assert(gicv3_driver_data->gicd_base);
	assert(gicv3_driver_data->g1s_interrupt_array ||
	       gicv3_driver_data->g0_interrupt_array);
124
125
126
127
128
129
130
131

	assert(IS_IN_EL3());

	/*
	 * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring
	 * the ARE_S bit. The Distributor might generate a system error
	 * otherwise.
	 */
132
	gicd_clr_ctlr(gicv3_driver_data->gicd_base,
133
134
135
136
137
138
		      CTLR_ENABLE_G0_BIT |
		      CTLR_ENABLE_G1S_BIT |
		      CTLR_ENABLE_G1NS_BIT,
		      RWP_TRUE);

	/* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */
139
	gicd_set_ctlr(gicv3_driver_data->gicd_base,
140
141
142
			CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE);

	/* Set the default attribute of all SPIs */
143
	gicv3_spis_configure_defaults(gicv3_driver_data->gicd_base);
144
145

	/* Configure the G1S SPIs */
146
147
148
149
	if (gicv3_driver_data->g1s_interrupt_array) {
		gicv3_secure_spis_configure(gicv3_driver_data->gicd_base,
					gicv3_driver_data->g1s_interrupt_num,
					gicv3_driver_data->g1s_interrupt_array,
150
					INTR_GROUP1S);
151
152
		bitmap |= CTLR_ENABLE_G1S_BIT;
	}
153
154

	/* Configure the G0 SPIs */
155
156
157
158
	if (gicv3_driver_data->g0_interrupt_array) {
		gicv3_secure_spis_configure(gicv3_driver_data->gicd_base,
					gicv3_driver_data->g0_interrupt_num,
					gicv3_driver_data->g0_interrupt_array,
159
					INTR_GROUP0);
160
161
		bitmap |= CTLR_ENABLE_G0_BIT;
	}
162
163

	/* Enable the secure SPIs now that they have been configured */
164
	gicd_set_ctlr(gicv3_driver_data->gicd_base, bitmap, RWP_TRUE);
165
166
167
168
169
170
171
172
173
174
175
}

/*******************************************************************************
 * This function initialises the GIC Redistributor interface of the calling CPU
 * (identified by the 'proc_num' parameter) based upon the data provided by the
 * platform while initialising the driver.
 ******************************************************************************/
void gicv3_rdistif_init(unsigned int proc_num)
{
	uintptr_t gicr_base;

176
177
178
179
180
181
182
	assert(gicv3_driver_data);
	assert(proc_num < gicv3_driver_data->rdistif_num);
	assert(gicv3_driver_data->rdistif_base_addrs);
	assert(gicv3_driver_data->gicd_base);
	assert(gicd_read_ctlr(gicv3_driver_data->gicd_base) & CTLR_ARE_S_BIT);
	assert(gicv3_driver_data->g1s_interrupt_array ||
	       gicv3_driver_data->g0_interrupt_array);
183
184
185

	assert(IS_IN_EL3());

186
187
188
	/* Power on redistributor */
	gicv3_rdistif_on(proc_num);

189
	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
190
191
192
193
194

	/* Set the default attribute of all SGIs and PPIs */
	gicv3_ppi_sgi_configure_defaults(gicr_base);

	/* Configure the G1S SGIs/PPIs */
195
	if (gicv3_driver_data->g1s_interrupt_array) {
196
		gicv3_secure_ppi_sgi_configure(gicr_base,
197
198
					gicv3_driver_data->g1s_interrupt_num,
					gicv3_driver_data->g1s_interrupt_array,
199
200
					INTR_GROUP1S);
	}
201
202

	/* Configure the G0 SGIs/PPIs */
203
	if (gicv3_driver_data->g0_interrupt_array) {
204
		gicv3_secure_ppi_sgi_configure(gicr_base,
205
206
					gicv3_driver_data->g0_interrupt_num,
					gicv3_driver_data->g0_interrupt_array,
207
208
					INTR_GROUP0);
	}
209
210
}

211
212
213
214
215
216
217
218
219
220
221
222
223
/*******************************************************************************
 * Functions to perform power operations on GIC Redistributor
 ******************************************************************************/
void gicv3_rdistif_off(unsigned int proc_num)
{
	return;
}

void gicv3_rdistif_on(unsigned int proc_num)
{
	return;
}

224
225
226
227
228
229
230
231
232
233
/*******************************************************************************
 * This function enables the GIC CPU interface of the calling CPU using only
 * system register accesses.
 ******************************************************************************/
void gicv3_cpuif_enable(unsigned int proc_num)
{
	uintptr_t gicr_base;
	unsigned int scr_el3;
	unsigned int icc_sre_el3;

234
235
236
	assert(gicv3_driver_data);
	assert(proc_num < gicv3_driver_data->rdistif_num);
	assert(gicv3_driver_data->rdistif_base_addrs);
237
238
239
	assert(IS_IN_EL3());

	/* Mark the connected core as awake */
240
	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
	gicv3_rdistif_mark_core_awake(gicr_base);

	/* Disable the legacy interrupt bypass */
	icc_sre_el3 = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT;

	/*
	 * Enable system register access for EL3 and allow lower exception
	 * levels to configure the same for themselves. If the legacy mode is
	 * not supported, the SRE bit is RAO/WI
	 */
	icc_sre_el3 |= (ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT);
	write_icc_sre_el3(read_icc_sre_el3() | icc_sre_el3);

	scr_el3 = read_scr_el3();

	/*
	 * Switch to NS state to write Non secure ICC_SRE_EL1 and
	 * ICC_SRE_EL2 registers.
	 */
	write_scr_el3(scr_el3 | SCR_NS_BIT);
	isb();

	write_icc_sre_el2(read_icc_sre_el2() | icc_sre_el3);
	write_icc_sre_el1(ICC_SRE_SRE_BIT);
	isb();

	/* Switch to secure state. */
	write_scr_el3(scr_el3 & (~SCR_NS_BIT));
	isb();

	/* Program the idle priority in the PMR */
	write_icc_pmr_el1(GIC_PRI_MASK);

	/* Enable Group0 interrupts */
	write_icc_igrpen0_el1(IGRPEN1_EL1_ENABLE_G0_BIT);

	/* Enable Group1 Secure interrupts */
	write_icc_igrpen1_el3(read_icc_igrpen1_el3() |
				IGRPEN1_EL3_ENABLE_G1S_BIT);

	/* Write the secure ICC_SRE_EL1 register */
	write_icc_sre_el1(ICC_SRE_SRE_BIT);
	isb();
}

/*******************************************************************************
 * This function disables the GIC CPU interface of the calling CPU using
 * only system register accesses.
 ******************************************************************************/
void gicv3_cpuif_disable(unsigned int proc_num)
{
	uintptr_t gicr_base;

294
295
296
	assert(gicv3_driver_data);
	assert(proc_num < gicv3_driver_data->rdistif_num);
	assert(gicv3_driver_data->rdistif_base_addrs);
297
298
299
300
301
302
303
304
305
306
307

	assert(IS_IN_EL3());

	/* Disable legacy interrupt bypass */
	write_icc_sre_el3(read_icc_sre_el3() |
			  (ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT));

	/* Disable Group0 interrupts */
	write_icc_igrpen0_el1(read_icc_igrpen0_el1() &
			      ~IGRPEN1_EL1_ENABLE_G0_BIT);

308
	/* Disable Group1 Secure and Non-Secure interrupts */
309
	write_icc_igrpen1_el3(read_icc_igrpen1_el3() &
310
311
			      ~(IGRPEN1_EL3_ENABLE_G1NS_BIT |
			      IGRPEN1_EL3_ENABLE_G1S_BIT));
312
313
314
315
316

	/* Synchronise accesses to group enable registers */
	isb();

	/* Mark the connected core as asleep */
317
	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
	gicv3_rdistif_mark_core_asleep(gicr_base);
}

/*******************************************************************************
 * This function returns the id of the highest priority pending interrupt at
 * the GIC cpu interface.
 ******************************************************************************/
unsigned int gicv3_get_pending_interrupt_id(void)
{
	unsigned int id;

	assert(IS_IN_EL3());
	id = read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK;

	/*
	 * If the ID is special identifier corresponding to G1S or G1NS
	 * interrupt, then read the highest pending group 1 interrupt.
	 */
	if ((id == PENDING_G1S_INTID) || (id == PENDING_G1NS_INTID))
		return read_icc_hppir1_el1() & HPPIR1_EL1_INTID_MASK;

	return id;
}

/*******************************************************************************
 * This function returns the type of the highest priority pending interrupt at
 * the GIC cpu interface. The return values can be one of the following :
 *   PENDING_G1S_INTID  : The interrupt type is secure Group 1.
 *   PENDING_G1NS_INTID : The interrupt type is non secure Group 1.
 *   0 - 1019           : The interrupt type is secure Group 0.
 *   GIC_SPURIOUS_INTERRUPT : there is no pending interrupt with
 *                            sufficient priority to be signaled
 ******************************************************************************/
unsigned int gicv3_get_pending_interrupt_type(void)
{
	assert(IS_IN_EL3());
	return read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK;
}

/*******************************************************************************
 * This function returns the type of the interrupt id depending upon the group
 * this interrupt has been configured under by the interrupt controller i.e.
 * group0 or group1 Secure / Non Secure. The return value can be one of the
 * following :
362
363
364
 *    INTR_GROUP0  : The interrupt type is a Secure Group 0 interrupt
 *    INTR_GROUP1S : The interrupt type is a Secure Group 1 secure interrupt
 *    INTR_GROUP1NS: The interrupt type is a Secure Group 1 non secure
365
366
367
368
369
370
371
372
373
 *                   interrupt.
 ******************************************************************************/
unsigned int gicv3_get_interrupt_type(unsigned int id,
					  unsigned int proc_num)
{
	unsigned int igroup, grpmodr;
	uintptr_t gicr_base;

	assert(IS_IN_EL3());
374
	assert(gicv3_driver_data);
375
376
377

	/* Ensure the parameters are valid */
	assert(id < PENDING_G1S_INTID || id >= MIN_LPI_ID);
378
	assert(proc_num < gicv3_driver_data->rdistif_num);
379
380
381

	/* All LPI interrupts are Group 1 non secure */
	if (id >= MIN_LPI_ID)
382
		return INTR_GROUP1NS;
383
384

	if (id < MIN_SPI_ID) {
385
386
		assert(gicv3_driver_data->rdistif_base_addrs);
		gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
387
388
389
		igroup = gicr_get_igroupr0(gicr_base, id);
		grpmodr = gicr_get_igrpmodr0(gicr_base, id);
	} else {
390
391
392
		assert(gicv3_driver_data->gicd_base);
		igroup = gicd_get_igroupr(gicv3_driver_data->gicd_base, id);
		grpmodr = gicd_get_igrpmodr(gicv3_driver_data->gicd_base, id);
393
394
395
396
397
398
399
	}

	/*
	 * If the IGROUP bit is set, then it is a Group 1 Non secure
	 * interrupt
	 */
	if (igroup)
400
		return INTR_GROUP1NS;
401
402
403

	/* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */
	if (grpmodr)
404
		return INTR_GROUP1S;
405
406

	/* Else it is a Group 0 Secure interrupt */
407
	return INTR_GROUP0;
408
}