fvp_common.c 12.3 KB
Newer Older
1
/*
2
 * Copyright (c) 2013-2020, 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
#include <assert.h>

#include <common/debug.h>
#include <drivers/arm/cci.h>
#include <drivers/arm/ccn.h>
#include <drivers/arm/gicv2.h>
13
14
#include <drivers/arm/sp804_delay_timer.h>
#include <drivers/generic_delay_timer.h>
15
#include <lib/mmio.h>
16
#include <lib/smccc.h>
17
#include <lib/xlat_tables/xlat_tables_compat.h>
18
#include <platform_def.h>
19
#include <services/arm_arch_svc.h>
20
#if SPM_MM
21
#include <services/spm_mm_partition.h>
22
#endif
23

24
25
26
27
#include <plat/arm/common/arm_config.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>

Roberto Vargas's avatar
Roberto Vargas committed
28
#include "fvp_private.h"
29

30
31
32
33
/* Defines for GIC Driver build time selection */
#define FVP_GICV2		1
#define FVP_GICV3		2

34
/*******************************************************************************
35
36
 * arm_config holds the characteristics of the differences between the three FVP
 * platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
37
38
39
 * at each boot stage by the primary before enabling the MMU (to allow
 * interconnect configuration) & used thereafter. Each BL will have its own copy
 * to allow independent operation.
40
 ******************************************************************************/
41
arm_config_t arm_config;
42
43
44
45
46
47
48
49
50

#define MAP_DEVICE0	MAP_REGION_FLAT(DEVICE0_BASE,			\
					DEVICE0_SIZE,			\
					MT_DEVICE | MT_RW | MT_SECURE)

#define MAP_DEVICE1	MAP_REGION_FLAT(DEVICE1_BASE,			\
					DEVICE1_SIZE,			\
					MT_DEVICE | MT_RW | MT_SECURE)

51
52
53
54
/*
 * Need to be mapped with write permissions in order to set a new non-volatile
 * counter value.
 */
55
56
#define MAP_DEVICE2	MAP_REGION_FLAT(DEVICE2_BASE,			\
					DEVICE2_SIZE,			\
57
					MT_DEVICE | MT_RW | MT_SECURE)
58

59
/*
60
 * Table of memory regions for various BL stages to map using the MMU.
61
62
 * This doesn't include Trusted SRAM as setup_page_tables() already takes care
 * of mapping it.
63
64
65
 *
 * The flash needs to be mapped as writable in order to erase the FIP's Table of
 * Contents in case of unrecoverable error (see plat_error_handler()).
66
 */
67
#ifdef IMAGE_BL1
68
69
const mmap_region_t plat_arm_mmap[] = {
	ARM_MAP_SHARED_RAM,
70
	V2M_MAP_FLASH0_RW,
71
	V2M_MAP_IOFPGA,
72
73
	MAP_DEVICE0,
	MAP_DEVICE1,
74
#if TRUSTED_BOARD_BOOT
75
76
77
	/* To access the Root of Trust Public Key registers. */
	MAP_DEVICE2,
	/* Map DRAM to authenticate NS_BL2U image. */
78
79
	ARM_MAP_NS_DRAM1,
#endif
80
81
82
	{0}
};
#endif
83
#ifdef IMAGE_BL2
84
85
const mmap_region_t plat_arm_mmap[] = {
	ARM_MAP_SHARED_RAM,
86
	V2M_MAP_FLASH0_RW,
87
	V2M_MAP_IOFPGA,
88
89
	MAP_DEVICE0,
	MAP_DEVICE1,
90
	ARM_MAP_NS_DRAM1,
91
#ifdef __aarch64__
92
93
	ARM_MAP_DRAM2,
#endif
94
95
96
#if defined(SPD_spmd)
	ARM_MAP_TRUSTED_DRAM,
#endif
97
#ifdef SPD_tspd
98
	ARM_MAP_TSP_SEC_MEM,
99
#endif
100
101
102
#if TRUSTED_BOARD_BOOT
	/* To access the Root of Trust Public Key registers. */
	MAP_DEVICE2,
103
#if !BL2_AT_EL3
104
	ARM_MAP_BL1_RW,
105
#endif
106
#endif /* TRUSTED_BOARD_BOOT */
107
#if SPM_MM
108
109
	ARM_SP_IMAGE_MMAP,
#endif
David Wang's avatar
David Wang committed
110
111
#if ARM_BL31_IN_DRAM
	ARM_MAP_BL31_SEC_DRAM,
112
113
#endif
#ifdef SPD_opteed
114
	ARM_MAP_OPTEE_CORE_MEM,
115
	ARM_OPTEE_PAGEABLE_LOAD_MEM,
David Wang's avatar
David Wang committed
116
#endif
117
118
119
	{0}
};
#endif
120
#ifdef IMAGE_BL2U
121
122
123
124
125
126
const mmap_region_t plat_arm_mmap[] = {
	MAP_DEVICE0,
	V2M_MAP_IOFPGA,
	{0}
};
#endif
127
#ifdef IMAGE_BL31
128
129
const mmap_region_t plat_arm_mmap[] = {
	ARM_MAP_SHARED_RAM,
Ambroise Vincent's avatar
Ambroise Vincent committed
130
131
132
133
#if USE_DEBUGFS
	/* Required by devfip, can be removed if devfip is not used */
	V2M_MAP_FLASH0_RW,
#endif /* USE_DEBUGFS */
134
	ARM_MAP_EL3_TZC_DRAM,
135
	V2M_MAP_IOFPGA,
136
137
	MAP_DEVICE0,
	MAP_DEVICE1,
138
	ARM_V2M_MAP_MEM_PROTECT,
139
#if SPM_MM
140
141
	ARM_SPM_BUF_EL3_MMAP,
#endif
142
	/* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */
143
	ARM_DTB_DRAM_NS,
144
145
146
	{0}
};

147
#if defined(IMAGE_BL31) && SPM_MM
148
149
const mmap_region_t plat_arm_secure_partition_mmap[] = {
	V2M_MAP_IOFPGA_EL0, /* for the UART */
150
151
152
	MAP_REGION_FLAT(DEVICE0_BASE,				\
			DEVICE0_SIZE,				\
			MT_DEVICE | MT_RO | MT_SECURE | MT_USER),
153
154
155
156
	ARM_SP_IMAGE_MMAP,
	ARM_SP_IMAGE_NS_BUF_MMAP,
	ARM_SP_IMAGE_RW_MMAP,
	ARM_SPM_BUF_EL0_MMAP,
157
158
159
	{0}
};
#endif
160
#endif
161
#ifdef IMAGE_BL32
162
const mmap_region_t plat_arm_mmap[] = {
163
#ifndef __aarch64__
164
	ARM_MAP_SHARED_RAM,
165
	ARM_V2M_MAP_MEM_PROTECT,
166
#endif
167
	V2M_MAP_IOFPGA,
168
169
	MAP_DEVICE0,
	MAP_DEVICE1,
170
	/* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */
171
	ARM_DTB_DRAM_NS,
172
173
	{0}
};
174
#endif
175

176
ARM_CASSERT_MMAP
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#if FVP_INTERCONNECT_DRIVER != FVP_CCN
static const int fvp_cci400_map[] = {
	PLAT_FVP_CCI400_CLUS0_SL_PORT,
	PLAT_FVP_CCI400_CLUS1_SL_PORT,
};

static const int fvp_cci5xx_map[] = {
	PLAT_FVP_CCI5XX_CLUS0_SL_PORT,
	PLAT_FVP_CCI5XX_CLUS1_SL_PORT,
};

static unsigned int get_interconnect_master(void)
{
	unsigned int master;
	u_register_t mpidr;

	mpidr = read_mpidr_el1();
195
	master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ?
196
197
198
199
200
201
		MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr);

	assert(master < FVP_CLUSTER_COUNT);
	return master;
}
#endif
202

203
#if defined(IMAGE_BL31) && SPM_MM
204
205
206
207
/*
 * Boot information passed to a secure partition during initialisation. Linear
 * indices in MP information will be filled at runtime.
 */
208
static spm_mm_mp_info_t sp_mp_info[] = {
209
210
211
212
213
214
215
216
217
218
	[0] = {0x80000000, 0},
	[1] = {0x80000001, 0},
	[2] = {0x80000002, 0},
	[3] = {0x80000003, 0},
	[4] = {0x80000100, 0},
	[5] = {0x80000101, 0},
	[6] = {0x80000102, 0},
	[7] = {0x80000103, 0},
};

219
const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
220
221
	.h.type              = PARAM_SP_IMAGE_BOOT_INFO,
	.h.version           = VERSION_1,
222
	.h.size              = sizeof(spm_mm_boot_info_t),
223
224
225
226
227
228
	.h.attr              = 0,
	.sp_mem_base         = ARM_SP_IMAGE_BASE,
	.sp_mem_limit        = ARM_SP_IMAGE_LIMIT,
	.sp_image_base       = ARM_SP_IMAGE_BASE,
	.sp_stack_base       = PLAT_SP_IMAGE_STACK_BASE,
	.sp_heap_base        = ARM_SP_IMAGE_HEAP_BASE,
229
	.sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
230
231
232
233
	.sp_shared_buf_base  = PLAT_SPM_BUF_BASE,
	.sp_image_size       = ARM_SP_IMAGE_SIZE,
	.sp_pcpu_stack_size  = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
	.sp_heap_size        = ARM_SP_IMAGE_HEAP_SIZE,
234
	.sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
235
236
237
238
239
240
241
242
243
244
245
	.sp_shared_buf_size  = PLAT_SPM_BUF_SIZE,
	.num_sp_mem_regions  = ARM_SP_IMAGE_NUM_MEM_REGIONS,
	.num_cpus            = PLATFORM_CORE_COUNT,
	.mp_info             = &sp_mp_info[0],
};

const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
{
	return plat_arm_secure_partition_mmap;
}

246
const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
247
248
249
250
251
252
		void *cookie)
{
	return &plat_arm_secure_partition_boot_info;
}
#endif

253
254
255
256
257
258
259
/*******************************************************************************
 * A single boot loader stack is expected to work on both the Foundation FVP
 * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
 * SYS_ID register provides a mechanism for detecting the differences between
 * these platforms. This information is stored in a per-BL array to allow the
 * code to take the correct path.Per BL platform configuration.
 ******************************************************************************/
260
void __init fvp_config_setup(void)
261
{
262
	unsigned int rev, hbi, bld, arch, sys_id;
263

264
265
266
267
268
	sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
	rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK;
	hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK;
	bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK;
	arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
269

270
271
	if (arch != ARCH_MODEL) {
		ERROR("This firmware is for FVP models\n");
272
		panic();
273
	}
274
275
276
277
278
279
280

	/*
	 * The build field in the SYS_ID tells which variant of the GIC
	 * memory is implemented by the model.
	 */
	switch (bld) {
	case BLD_GIC_VE_MMAP:
281
282
		ERROR("Legacy Versatile Express memory map for GIC peripheral"
				" is not supported\n");
283
		panic();
284
285
286
287
		break;
	case BLD_GIC_A53A57_MMAP:
		break;
	default:
288
289
		ERROR("Unsupported board build %x\n", bld);
		panic();
290
291
292
293
294
295
296
	}

	/*
	 * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010
	 * for the Foundation FVP.
	 */
	switch (hbi) {
297
298
	case HBI_FOUNDATION_FVP:
		arm_config.flags = 0;
299
300
301
302
303
304

		/*
		 * Check for supported revisions of Foundation FVP
		 * Allow future revisions to run but emit warning diagnostic
		 */
		switch (rev) {
305
306
307
		case REV_FOUNDATION_FVP_V2_0:
		case REV_FOUNDATION_FVP_V2_1:
		case REV_FOUNDATION_FVP_v9_1:
308
		case REV_FOUNDATION_FVP_v9_6:
309
310
311
312
313
			break;
		default:
			WARN("Unrecognized Foundation FVP revision %x\n", rev);
			break;
		}
314
		break;
315
	case HBI_BASE_FVP:
316
		arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC);
317
318
319
320
321
322

		/*
		 * Check for supported revisions
		 * Allow future revisions to run but emit warning diagnostic
		 */
		switch (rev) {
323
		case REV_BASE_FVP_V0:
324
325
326
			arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400;
			break;
		case REV_BASE_FVP_REVC:
327
			arm_config.flags |= (ARM_CONFIG_FVP_HAS_SMMUV3 |
328
					ARM_CONFIG_FVP_HAS_CCI5XX);
329
330
331
332
333
			break;
		default:
			WARN("Unrecognized Base FVP revision %x\n", rev);
			break;
		}
334
335
		break;
	default:
336
337
		ERROR("Unsupported board HBI number 0x%x\n", hbi);
		panic();
338
	}
339
340
341
342
343
344

	/*
	 * We assume that the presence of MT bit, and therefore shifted
	 * affinities, is uniform across the platform: either all CPUs, or no
	 * CPUs implement it.
	 */
345
	if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U)
346
		arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF;
347
}
348

349

350
void __init fvp_interconnect_init(void)
351
{
352
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
353
	if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) {
354
		ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported");
355
356
357
358
359
		panic();
	}

	plat_arm_interconnect_init();
#else
360
361
362
	uintptr_t cci_base = 0U;
	const int *cci_map = NULL;
	unsigned int map_size = 0U;
363
364

	/* Initialize the right interconnect */
365
	if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) {
366
367
368
		cci_base = PLAT_FVP_CCI5XX_BASE;
		cci_map = fvp_cci5xx_map;
		map_size = ARRAY_SIZE(fvp_cci5xx_map);
369
	} else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) {
370
371
372
		cci_base = PLAT_FVP_CCI400_BASE;
		cci_map = fvp_cci400_map;
		map_size = ARRAY_SIZE(fvp_cci400_map);
373
374
	} else {
		return;
375
	}
376

377
378
	assert(cci_base != 0U);
	assert(cci_map != NULL);
379
380
	cci_init(cci_base, cci_map, map_size);
#endif
381
382
}

383
void fvp_interconnect_enable(void)
384
{
385
386
387
388
389
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
	plat_arm_interconnect_enter_coherency();
#else
	unsigned int master;

390
391
	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
				 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
392
393
394
395
		master = get_interconnect_master();
		cci_enable_snoop_dvm_reqs(master);
	}
#endif
396
397
}

398
void fvp_interconnect_disable(void)
399
{
400
401
402
403
404
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
	plat_arm_interconnect_exit_coherency();
#else
	unsigned int master;

405
406
	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
				 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
407
408
409
410
		master = get_interconnect_master();
		cci_disable_snoop_dvm_reqs(master);
	}
#endif
411
}
412

413
#if TRUSTED_BOARD_BOOT
414
415
416
417
418
419
420
421
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
{
	assert(heap_addr != NULL);
	assert(heap_size != NULL);

	return arm_get_mbedtls_heap(heap_addr, heap_size);
}
#endif
422
423
424

void fvp_timer_init(void)
{
425
#if USE_SP804_TIMER
426
427
428
429
430
431
432
433
434
435
436
437
438
439
	/* Enable the clock override for SP804 timer 0, which means that no
	 * clock dividers are applied and the raw (35MHz) clock will be used.
	 */
	mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV);

	/* Initialize delay timer driver using SP804 dual timer 0 */
	sp804_timer_init(V2M_SP804_TIMER0_BASE,
			SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
#else
	generic_delay_timer_init();

	/* Enable System level generic timer */
	mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
			CNTCR_FCREQ(0U) | CNTCR_EN);
440
#endif /* USE_SP804_TIMER */
441
}
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

/*****************************************************************************
 * plat_is_smccc_feature_available() - This function checks whether SMCCC
 *                                     feature is availabile for platform.
 * @fid: SMCCC function id
 *
 * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
 * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
 *****************************************************************************/
int32_t plat_is_smccc_feature_available(u_register_t fid)
{
	switch (fid) {
	case SMCCC_ARCH_SOC_ID:
		return SMC_ARCH_CALL_SUCCESS;
	default:
		return SMC_ARCH_CALL_NOT_SUPPORTED;
	}
}

/* Get SOC version */
int32_t plat_get_soc_version(void)
{
	return (int32_t)
		((ARM_SOC_IDENTIFICATION_CODE << ARM_SOC_IDENTIFICATION_SHIFT)
		 | (ARM_SOC_CONTINUATION_CODE << ARM_SOC_CONTINUATION_SHIFT)
		 | FVP_SOC_ID);
}

/* Get SOC revision */
int32_t plat_get_soc_revision(void)
{
	unsigned int sys_id;

	sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
	return (int32_t)((sys_id >> V2M_SYS_ID_REV_SHIFT) &
			V2M_SYS_ID_REV_MASK);
}