xref: /optee_os/core/drivers/tzc380.c (revision 1bb929836182ecb96d2d9d268daa807c67596396)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2017 NXP
4  * All rights reserved.
5  *
6  * Peng Fan <peng.fan@nxp.com>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <assert.h>
32 #include <drivers/tzc380.h>
33 #include <io.h>
34 #include <kernel/panic.h>
35 #include <stddef.h>
36 #include <trace.h>
37 #include <util.h>
38 
39 /*
40  * Implementation defined values used to validate inputs later.
41  * Filters : max of 4 ; 0 to 3
42  * Regions : max of 9 ; 0 to 8
43  * Address width : Values between 32 to 64
44  */
45 struct tzc_instance {
46 	vaddr_t base;
47 	uint8_t addr_width;
48 	uint8_t num_regions;
49 };
50 
51 static struct tzc_instance tzc;
52 
53 static uint32_t tzc_read_build_config(vaddr_t base)
54 {
55 	return read32(base + BUILD_CONFIG_OFF);
56 }
57 
58 static void tzc_write_action(vaddr_t base, enum tzc_action action)
59 {
60 	write32(action, base + ACTION_OFF);
61 }
62 
63 static void tzc_write_region_base_low(vaddr_t base, uint32_t region,
64 				      uint32_t val)
65 {
66 	write32(val, base + REGION_SETUP_LOW_OFF(region));
67 }
68 
69 static void tzc_write_region_base_high(vaddr_t base, uint32_t region,
70 				       uint32_t val)
71 {
72 	write32(val, base + REGION_SETUP_HIGH_OFF(region));
73 }
74 
75 static void tzc_write_region_attributes(vaddr_t base, uint32_t region,
76 					uint32_t val)
77 {
78 	write32(val, base + REGION_ATTRIBUTES_OFF(region));
79 }
80 
81 void tzc_init(vaddr_t base)
82 {
83 	uint32_t tzc_build;
84 
85 	assert(base);
86 	tzc.base = base;
87 
88 	/* Save values we will use later. */
89 	tzc_build = tzc_read_build_config(tzc.base);
90 	tzc.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
91 			   BUILD_CONFIG_AW_MASK) + 1;
92 	tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
93 			   BUILD_CONFIG_NR_MASK) + 1;
94 }
95 
96 static uint32_t addr_low(vaddr_t addr)
97 {
98 	return (uint32_t)addr;
99 }
100 
101 static uint32_t addr_high(vaddr_t addr __maybe_unused)
102 {
103 #if (UINTPTR_MAX == UINT64_MAX)
104 	return addr >> 32;
105 #else
106 	return 0;
107 #endif
108 }
109 
110 
111 /*
112  * `tzc_configure_region` is used to program regions into the TrustZone
113  * controller.
114  */
115 void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr)
116 {
117 	assert(tzc.base);
118 
119 	assert(region < tzc.num_regions);
120 
121 	tzc_write_region_base_low(tzc.base, region, addr_low(region_base));
122 	tzc_write_region_base_high(tzc.base, region, addr_high(region_base));
123 	tzc_write_region_attributes(tzc.base, region, attr);
124 }
125 
126 void tzc_set_action(enum tzc_action action)
127 {
128 	assert(tzc.base);
129 
130 	/*
131 	 * - Currently no handler is provided to trap an error via interrupt
132 	 *   or exception.
133 	 * - The interrupt action has not been tested.
134 	 */
135 	tzc_write_action(tzc.base, action);
136 }
137 
138 #if TRACE_LEVEL >= TRACE_DEBUG
139 
140 static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region)
141 {
142 	return read32(base + REGION_ATTRIBUTES_OFF(region));
143 }
144 
145 static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region)
146 {
147 	return read32(base + REGION_SETUP_LOW_OFF(region));
148 }
149 
150 static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region)
151 {
152 	return read32(base + REGION_SETUP_HIGH_OFF(region));
153 }
154 
155 #define	REGION_MAX	16
156 void tzc_dump_state(void)
157 {
158 	uint32_t n;
159 	uint32_t temp_32reg, temp_32reg_h;
160 
161 	DMSG("enter");
162 	DMSG("security_inversion_en %x\n",
163 	     read32(tzc.base + SECURITY_INV_EN_OFF));
164 	for (n = 0; n <= REGION_MAX; n++) {
165 		temp_32reg = tzc_read_region_attributes(tzc.base, n);
166 		if (!(temp_32reg & TZC_ATTR_REGION_EN_MASK))
167 			continue;
168 
169 		DMSG("\n");
170 		DMSG("region %d", n);
171 		temp_32reg = tzc_read_region_base_low(tzc.base, n);
172 		temp_32reg_h = tzc_read_region_base_high(tzc.base, n);
173 		DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg);
174 		temp_32reg = tzc_read_region_attributes(tzc.base, n);
175 		DMSG("region sp: %x", temp_32reg >> TZC_ATTR_SP_SHIFT);
176 		DMSG("region size: %x\n", (temp_32reg & TZC_REGION_SIZE_MASK) >>
177 				TZC_REGION_SIZE_SHIFT);
178 	}
179 	DMSG("exit");
180 }
181 
182 #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */
183