1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) 2017 Marvell International Ltd.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <initcall.h>
30 #include <io.h>
31 #include <kernel/panic.h>
32 #include <mm/core_memprot.h>
33 #include <util.h>
34
35 #define PHY_2_VIR(addr) ((vaddr_t)phys_to_virt((addr), MEM_AREA_IO_SEC, 1))
36
37 #define MCU_BASE 0xD0000000
38 #define MCU_MC_CONTROL_0_REG PHY_2_VIR(MCU_BASE + 0x044)
39 #define TRUSTZONE_LOCK BIT(31)
40
41 #define MCU_TZ_RANGE_HIGH_REG(x) PHY_2_VIR(MCU_BASE + 0x84 + ((x) << 3))
42 #define MCU_TZ_RANGE_LOW_REG(x) PHY_2_VIR(MCU_BASE + 0x80 + ((x) << 3))
43
44 #define RW_PERM 0x0
45 #define RO_PERM 0x1
46 #define WO_PERM 0x2
47 #define ABORT_PERM 0x3
48
49 #define MAX_RANGE_NUM 16
50 #define INVALID_SIZE_CODE 0xff
51
52 #ifdef TEE_RES_CFG_16M
53 #define RSVD_SEC_MEM (SIZE_8M + SIZE_8M)
54 #elif defined(TEE_RES_CFG_24M)
55 #define RSVD_SEC_MEM (SIZE_8M + SIZE_8M + SIZE_8M)
56 #elif defined(TEE_RES_CFG_8M)
57 #define RSVD_SEC_MEM SIZE_8M
58 #else
59 #error "no reserved secure memory defined."
60 #endif
61
62 #define RA_ADDR TZDRAM_BASE
63 #define RA_SIZE TZDRAM_SIZE
64 #define RA_PERM ABORT_PERM
65
66 #define TZ_IS_VALID(data) ((data) & (0x1))
67 #define TZ_SET_VALID(data) ((data) |= (0x1))
68
69 #define TZ_GET_PERM(data, ret) ((ret) = (((data) & (0x3 << 1)) >> 1))
70 #define TZ_SET_PERM(data, val) \
71 do { \
72 (data) &= (~(0x3 << 1)); \
73 (data) |= (((val) & 0x3) << 1); \
74 } while (0)
75
76 #define TZ_GET_RZ_EN(data, ret) ((ret) = (((data) & (0x1 << 3)) >> 3))
77 #define TZ_SET_RZ_EN(data, val) \
78 do { \
79 (data) &= (~(0x1 << 3)); \
80 (data) |= (((val) & 0x1) << 3); \
81 } while (0)
82
83 #define TZ_GET_AREA_LEN_CODE(data, ret) ((ret) = (((data) & (0x1F << 8)) >> 8))
84
85 #define TZ_SET_AREA_LEN_CODE(data, val) \
86 do { \
87 (data) &= (~(0x1F << 8)); \
88 (data) |= (((val) & 0x1F) << 8); \
89 } while (0)
90
91 #define TZ_GET_START_ADDR_L(data, ret) \
92 ((ret) = (((data) & 0xFFF00000)))
93
94 #define TZ_SET_START_ADDR_L(data, val) \
95 do { \
96 (data) &= (~0xFFF00000); \
97 (data) |= (((val) & 0xFFF00000)); \
98 } while (0)
99
100 #define TZ_GET_UR_PERM(data, val) ((ret) = (((data) & (0x3 << 4)) >> 4))
101 #define TZ_SET_UR_PERM(data, val) \
102 do { \
103 (data) &= (~(0x3 << 4)); \
104 (data) |= (((val) & 0x3) << 4); \
105 } while (0)
106
107 #define TZ_GET_UR_RZ_EN(data, val) \
108 ((ret) = (((data) & (0x1 << 6)) >> 6))
109
110 #define TZ_SET_UR_RZ_EN(data, val) \
111 do { \
112 (data) &= (~(0x1 << 6)); \
113 (data) |= (((val) & 0x1) << 6); \
114 } while (0)
115
116 /* armada3700 mini region size is 1M */
117 #define RANGE_SIZE_TO_CODE(size, code, i) \
118 do { \
119 (code) = INVALID_SIZE_CODE; \
120 for ((i) = 0; (i) <= 0x1d; (i)++) { \
121 if (((uint32_t)0x1 << (i)) == ((size) >> 20)) { \
122 (code) = (i); \
123 break; \
124 } \
125 } \
126 } while (0)
127
128 #define TZ_LOCK_MC(x) \
129 do { \
130 (x) = io_read32(MCU_MC_CONTROL_0_REG); \
131 (x) |= (TRUSTZONE_LOCK); \
132 io_write32(MCU_MC_CONTROL_0_REG, (x)); \
133 } while (0)
134
135 register_phys_mem_pgdir(MEM_AREA_IO_SEC, MCU_BASE, CORE_MMU_PGDIR_SIZE);
136
_find_valid_range(void)137 static int32_t _find_valid_range(void)
138 {
139 uint32_t i;
140 uint32_t tmp;
141
142 for (i = 0; i < MAX_RANGE_NUM; i++) {
143 tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i));
144 if (!TZ_IS_VALID(tmp))
145 return i;
146 }
147 return -1;
148 }
149
set_range(uint32_t addr,uint32_t size,uint32_t perm)150 static int32_t set_range(uint32_t addr, uint32_t size, uint32_t perm)
151 {
152 uint32_t data;
153 uint32_t sizecode;
154 int32_t valid_range;
155 uint32_t i;
156
157 if (!IS_ALIGNED(addr, SIZE_1M)) {
158 EMSG("region addr(0x%" PRIx32 ") is not aligned with 1M!",
159 addr);
160 return -1;
161 }
162
163 if (!IS_ALIGNED(size, SIZE_1M)) {
164 EMSG("region size(0x%" PRIx32 ") is not aligned with 1M!",
165 size);
166 return -1;
167 }
168
169 RANGE_SIZE_TO_CODE(size, sizecode, i);
170 if (sizecode == INVALID_SIZE_CODE) {
171 EMSG("not valid region size(2^n)! size:0x%" PRIx32, size);
172 return -1;
173 }
174
175 valid_range = _find_valid_range();
176 if (valid_range == -1) {
177 EMSG("ERR: can't find valid range!");
178 return -1;
179 }
180
181 data = io_read32(MCU_TZ_RANGE_LOW_REG(valid_range));
182
183 TZ_SET_VALID(data);
184 TZ_SET_PERM(data, perm);
185 TZ_SET_AREA_LEN_CODE(data, sizecode);
186 TZ_SET_START_ADDR_L(data, addr);
187
188 if (!valid_range) {
189 /* Set Undefine Range RW */
190 TZ_SET_UR_PERM(data, RW_PERM);
191 TZ_SET_UR_RZ_EN(data, 0);
192 }
193
194 io_write32(MCU_TZ_RANGE_LOW_REG(valid_range), data);
195
196 return 0;
197 }
198
_dump_range(void)199 static void _dump_range(void)
200 {
201 uint32_t i;
202 uint32_t tmp;
203 uint32_t __maybe_unused sizecode_read;
204 uint32_t __maybe_unused sizem;
205 uint32_t __maybe_unused addr_read;
206 uint32_t __maybe_unused perm_read;
207
208 for (i = 0; i < MAX_RANGE_NUM; i++) {
209 tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i));
210
211 if (TZ_IS_VALID(tmp)) {
212 TZ_GET_PERM(tmp, perm_read);
213 TZ_GET_AREA_LEN_CODE(tmp, sizecode_read);
214 TZ_GET_START_ADDR_L(tmp, addr_read);
215
216 DMSG("Range Num%" PRIu32
217 ": Reg 0x%" PRIx64 " = 0x%" PRIx32,
218 i, MCU_TZ_RANGE_LOW_REG(i), tmp);
219 DMSG("AddrL: 0x%08" PRIx32, addr_read);
220 DMSG("Size: %" PRIu32 "M", (0x1 << sizecode_read));
221 DMSG("Perm: %" PRIu32, perm_read);
222 }
223 }
224 }
225
_set_range(uint32_t addr,uint32_t size,uint32_t perm)226 static void _set_range(uint32_t addr, uint32_t size, uint32_t perm)
227 {
228 uint32_t rgn_addr = addr;
229 uint32_t rgn_size = size;
230 /* minimum region size is 1M and must be times of 1M */
231 uint32_t p = 0x100000;
232
233 while (1) {
234 if ((p * 2) > rgn_size) {
235 set_range(rgn_addr, p, perm);
236 rgn_addr += p;
237 rgn_size -= p;
238 if (rgn_size == 0)
239 break;
240 p = 0x100000;
241 } else
242 p <<= 1;
243 }
244 }
245
init_sec_perf(void)246 static TEE_Result init_sec_perf(void)
247 {
248 uint32_t tmp;
249
250 /* Set Secure Memory Region */
251 DMSG("sec-rgn size: ra = 0x%" PRIx32 ", size = 0x%" PRIx64,
252 RA_ADDR, RA_SIZE);
253 _set_range(RA_ADDR, RA_SIZE, RA_PERM);
254
255 /* Close TZ register modification */
256 TZ_LOCK_MC(tmp);
257
258 _dump_range();
259
260 return TEE_SUCCESS;
261 }
262
263 service_init(init_sec_perf);
264