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