tzc380.c 2.37 KB
Newer Older
Peng Fan's avatar
Peng Fan committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
/*
 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <debug.h>
#include <mmio.h>
#include <stddef.h>
#include <tzc380.h>

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

static void tzc380_write_action(uintptr_t base, tzc_action_t action)
{
	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
53
	assert(base != 0U);
Peng Fan's avatar
Peng Fan committed
54
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
	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
84
	assert(tzc380.base != 0U);
Peng Fan's avatar
Peng Fan committed
85
86
87
88
89
90
91
92
93
94

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

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

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