tzc380.c 2.39 KB
Newer Older
Peng Fan's avatar
Peng Fan committed
1
2
3
4
5
6
7
8
/*
 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <stddef.h>
9
10
11
12

#include <common/debug.h>
#include <drivers/arm/tzc380.h>
#include <lib/mmio.h>
Peng Fan's avatar
Peng Fan committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26

struct tzc380_instance {
	uintptr_t base;
	uint8_t addr_width;
	uint8_t num_regions;
};

struct tzc380_instance tzc380;

static unsigned int tzc380_read_build_config(uintptr_t base)
{
	return mmio_read_32(base + TZC380_CONFIGURATION_OFF);
}

27
static void tzc380_write_action(uintptr_t base, unsigned int action)
Peng Fan's avatar
Peng Fan committed
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
{
	mmio_write_32(base + ACTION_OFF, action);
}

static void tzc380_write_region_base_low(uintptr_t base, unsigned int region,
				      unsigned int val)
{
	mmio_write_32(base + REGION_SETUP_LOW_OFF(region), val);
}

static void tzc380_write_region_base_high(uintptr_t base, unsigned int region,
				       unsigned int val)
{
	mmio_write_32(base + REGION_SETUP_HIGH_OFF(region), val);
}

static void tzc380_write_region_attributes(uintptr_t base, unsigned int region,
					unsigned int val)
{
	mmio_write_32(base + REGION_ATTRIBUTES_OFF(region), val);
}

void tzc380_init(uintptr_t base)
{
	unsigned int tzc_build;

Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
54
	assert(base != 0U);
Peng Fan's avatar
Peng Fan committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
	tzc380.base = base;

	/* Save values we will use later. */
	tzc_build = tzc380_read_build_config(tzc380.base);
	tzc380.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
			      BUILD_CONFIG_AW_MASK) + 1;
	tzc380.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
			       BUILD_CONFIG_NR_MASK) + 1;
}

static uint32_t addr_low(uintptr_t addr)
{
	return (uint32_t)addr;
}

static uint32_t addr_high(uintptr_t addr __unused)
{
#if (UINTPTR_MAX == UINT64_MAX)
	return addr >> 32;
#else
	return 0;
#endif
}

/*
 * `tzc380_configure_region` is used to program regions into the TrustZone
 * controller.
 */
void tzc380_configure_region(uint8_t region, uintptr_t region_base, unsigned int attr)
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
85
	assert(tzc380.base != 0U);
Peng Fan's avatar
Peng Fan committed
86
87
88
89
90
91
92
93

	assert(region < tzc380.num_regions);

	tzc380_write_region_base_low(tzc380.base, region, addr_low(region_base));
	tzc380_write_region_base_high(tzc380.base, region, addr_high(region_base));
	tzc380_write_region_attributes(tzc380.base, region, attr);
}

94
void tzc380_set_action(unsigned int action)
Peng Fan's avatar
Peng Fan committed
95
{
Antonio Nino Diaz's avatar
Antonio Nino Diaz committed
96
	assert(tzc380.base != 0U);
Peng Fan's avatar
Peng Fan committed
97
98
99
100
101
102
103
104

	/*
	 * - Currently no handler is provided to trap an error via interrupt
	 *   or exception.
	 * - The interrupt action has not been tested.
	 */
	tzc380_write_action(tzc380.base, action);
}