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