fvp_common.c 12.4 KB
Newer Older
1
/*
2
 * Copyright (c) 2013-2021, 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
	MAP_DEVICE0,
73
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
74
	MAP_DEVICE1,
75
#endif
76
#if TRUSTED_BOARD_BOOT
77
78
79
	/* To access the Root of Trust Public Key registers. */
	MAP_DEVICE2,
	/* Map DRAM to authenticate NS_BL2U image. */
80
81
	ARM_MAP_NS_DRAM1,
#endif
82
83
84
	{0}
};
#endif
85
#ifdef IMAGE_BL2
86
87
const mmap_region_t plat_arm_mmap[] = {
	ARM_MAP_SHARED_RAM,
88
	V2M_MAP_FLASH0_RW,
89
	V2M_MAP_IOFPGA,
90
	MAP_DEVICE0,
91
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
92
	MAP_DEVICE1,
93
#endif
94
	ARM_MAP_NS_DRAM1,
95
#ifdef __aarch64__
96
97
	ARM_MAP_DRAM2,
#endif
98
99
100
#if defined(SPD_spmd)
	ARM_MAP_TRUSTED_DRAM,
#endif
101
#ifdef SPD_tspd
102
	ARM_MAP_TSP_SEC_MEM,
103
#endif
104
105
106
#if TRUSTED_BOARD_BOOT
	/* To access the Root of Trust Public Key registers. */
	MAP_DEVICE2,
107
#if !BL2_AT_EL3
108
	ARM_MAP_BL1_RW,
109
#endif
110
#endif /* TRUSTED_BOARD_BOOT */
111
#if SPM_MM
112
113
	ARM_SP_IMAGE_MMAP,
#endif
David Wang's avatar
David Wang committed
114
115
#if ARM_BL31_IN_DRAM
	ARM_MAP_BL31_SEC_DRAM,
116
117
#endif
#ifdef SPD_opteed
118
	ARM_MAP_OPTEE_CORE_MEM,
119
	ARM_OPTEE_PAGEABLE_LOAD_MEM,
David Wang's avatar
David Wang committed
120
#endif
121
122
123
	{0}
};
#endif
124
#ifdef IMAGE_BL2U
125
126
127
128
129
130
const mmap_region_t plat_arm_mmap[] = {
	MAP_DEVICE0,
	V2M_MAP_IOFPGA,
	{0}
};
#endif
131
#ifdef IMAGE_BL31
132
133
const mmap_region_t plat_arm_mmap[] = {
	ARM_MAP_SHARED_RAM,
Ambroise Vincent's avatar
Ambroise Vincent committed
134
135
136
137
#if USE_DEBUGFS
	/* Required by devfip, can be removed if devfip is not used */
	V2M_MAP_FLASH0_RW,
#endif /* USE_DEBUGFS */
138
	ARM_MAP_EL3_TZC_DRAM,
139
	V2M_MAP_IOFPGA,
140
141
	MAP_DEVICE0,
	MAP_DEVICE1,
142
	ARM_V2M_MAP_MEM_PROTECT,
143
#if SPM_MM
144
145
	ARM_SPM_BUF_EL3_MMAP,
#endif
146
	/* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */
147
	ARM_DTB_DRAM_NS,
148
149
150
	{0}
};

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

180
ARM_CASSERT_MMAP
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#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();
199
	master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ?
200
201
202
203
204
205
		MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr);

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

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

223
const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
224
225
	.h.type              = PARAM_SP_IMAGE_BOOT_INFO,
	.h.version           = VERSION_1,
226
	.h.size              = sizeof(spm_mm_boot_info_t),
227
228
229
230
231
232
	.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,
233
	.sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
234
235
236
237
	.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,
238
	.sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
239
240
241
242
243
244
245
246
247
248
249
	.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;
}

250
const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
251
252
253
254
255
256
		void *cookie)
{
	return &plat_arm_secure_partition_boot_info;
}
#endif

257
258
259
260
261
262
263
/*******************************************************************************
 * 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.
 ******************************************************************************/
264
void __init fvp_config_setup(void)
265
{
266
	unsigned int rev, hbi, bld, arch, sys_id;
267

268
269
270
271
272
	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;
273

274
275
	if (arch != ARCH_MODEL) {
		ERROR("This firmware is for FVP models\n");
276
		panic();
277
	}
278
279
280
281
282
283
284

	/*
	 * 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:
285
286
		ERROR("Legacy Versatile Express memory map for GIC peripheral"
				" is not supported\n");
287
		panic();
288
289
290
291
		break;
	case BLD_GIC_A53A57_MMAP:
		break;
	default:
292
293
		ERROR("Unsupported board build %x\n", bld);
		panic();
294
295
296
297
298
299
300
	}

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

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

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

	/*
	 * 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.
	 */
349
	if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U)
350
		arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF;
351
}
352

353

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

	plat_arm_interconnect_init();
#else
364
365
366
	uintptr_t cci_base = 0U;
	const int *cci_map = NULL;
	unsigned int map_size = 0U;
367
368

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

381
382
	assert(cci_base != 0U);
	assert(cci_map != NULL);
383
384
	cci_init(cci_base, cci_map, map_size);
#endif
385
386
}

387
void fvp_interconnect_enable(void)
388
{
389
390
391
392
393
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
	plat_arm_interconnect_enter_coherency();
#else
	unsigned int master;

394
395
	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
				 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
396
397
398
399
		master = get_interconnect_master();
		cci_enable_snoop_dvm_reqs(master);
	}
#endif
400
401
}

402
void fvp_interconnect_disable(void)
403
{
404
405
406
407
408
#if FVP_INTERCONNECT_DRIVER == FVP_CCN
	plat_arm_interconnect_exit_coherency();
#else
	unsigned int master;

409
410
	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
				 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
411
412
413
414
		master = get_interconnect_master();
		cci_disable_snoop_dvm_reqs(master);
	}
#endif
415
}
416

417
#if TRUSTED_BOARD_BOOT
418
419
420
421
422
423
424
425
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
426
427
428

void fvp_timer_init(void)
{
429
#if USE_SP804_TIMER
430
431
432
433
434
435
436
437
438
439
440
441
442
443
	/* 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);
444
#endif /* USE_SP804_TIMER */
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
479
480
481
482

/*****************************************************************************
 * 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);
}