1 // SPDX-License-Identifier: BSD-Source-Code
2 /*
3  * Copyright (c) 2013, Atmel Corporation
4  * Copyright (c) 2017, Timesys Corporation
5  *
6  * All rights reserved.
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  * - Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the disclaimer below.
13  *
14  * Atmel's name may not be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 #include <arm32.h>
29 #include <io.h>
30 #include <sama5d2.h>
31 #include <platform_config.h>
32 #include <stdint.h>
33 #include <matrix.h>
34 #include <tz_matrix.h>
35 #include <trace.h>
36 
37 #define MATRIX_AXIMX	1
38 #define MATRIX_H64MX	2
39 #define MATRIX_H32MX	3
40 
41 #define SECURITY_TYPE_AS	1
42 #define SECURITY_TYPE_NS	2
43 #define SECURITY_TYPE_PS	3
44 
45 #define WORLD_NON_SECURE	0
46 #define WORLD_SECURE		1
47 
48 struct peri_security {
49 	unsigned int peri_id;
50 	unsigned int matrix;
51 	unsigned int security_type;
52 };
53 
54 static const struct peri_security peri_security_array[] = {
55 	{
56 		.peri_id = AT91C_ID_PMC,
57 		.matrix = MATRIX_H64MX,
58 		.security_type = SECURITY_TYPE_PS,
59 	},
60 	{
61 		.peri_id = AT91C_ID_ARM,
62 		.matrix = MATRIX_H64MX,
63 		.security_type = SECURITY_TYPE_PS,
64 	},
65 	{
66 		.peri_id = AT91C_ID_PIT,
67 		.matrix = MATRIX_H32MX,
68 		.security_type = SECURITY_TYPE_PS,
69 	},
70 	{
71 		.peri_id = AT91C_ID_WDT,
72 		.matrix = MATRIX_H32MX,
73 		.security_type = SECURITY_TYPE_PS,
74 	},
75 	{
76 		.peri_id = AT91C_ID_GMAC,
77 		.matrix = MATRIX_H32MX,
78 		.security_type = SECURITY_TYPE_PS,
79 	},
80 	{
81 		.peri_id = AT91C_ID_XDMAC0,
82 		.matrix = MATRIX_H64MX,
83 		.security_type = SECURITY_TYPE_PS,
84 	},
85 	{
86 		.peri_id = AT91C_ID_XDMAC1,
87 		.matrix = MATRIX_H64MX,
88 		.security_type = SECURITY_TYPE_PS,
89 	},
90 	{
91 		.peri_id = AT91C_ID_ICM,
92 		.matrix = MATRIX_H32MX,
93 		.security_type = SECURITY_TYPE_PS,
94 	},
95 	{
96 		.peri_id = AT91C_ID_AES,
97 		.matrix = MATRIX_H64MX,
98 		.security_type = SECURITY_TYPE_PS,
99 	},
100 	{
101 		.peri_id = AT91C_ID_AESB,
102 		.matrix = MATRIX_H64MX,
103 		.security_type = SECURITY_TYPE_PS,
104 	},
105 	{
106 		.peri_id = AT91C_ID_TDES,
107 		.matrix = MATRIX_H32MX,
108 		.security_type = SECURITY_TYPE_PS,
109 	},
110 	{
111 		.peri_id = AT91C_ID_SHA,
112 		.matrix = MATRIX_H64MX,
113 		.security_type = SECURITY_TYPE_PS,
114 	},
115 	{
116 		.peri_id = AT91C_ID_MPDDRC,
117 		.matrix = MATRIX_H64MX,
118 		.security_type = SECURITY_TYPE_PS,
119 	},
120 	{
121 		.peri_id = AT91C_ID_MATRIX1,
122 		.matrix = MATRIX_H32MX,
123 		.security_type = SECURITY_TYPE_AS,
124 	},
125 	{
126 		.peri_id = AT91C_ID_MATRIX0,
127 		.matrix = MATRIX_H64MX,
128 		.security_type = SECURITY_TYPE_AS,
129 	},
130 	{
131 		.peri_id = AT91C_ID_SECUMOD,
132 		.matrix = MATRIX_H32MX,
133 		.security_type = SECURITY_TYPE_AS,
134 	},
135 	{
136 		.peri_id = AT91C_ID_HSMC,
137 		.matrix = MATRIX_H32MX,
138 		.security_type = SECURITY_TYPE_PS,
139 	},
140 	{
141 		.peri_id = AT91C_ID_PIOA,
142 		.matrix = MATRIX_H32MX,
143 		.security_type = SECURITY_TYPE_AS,
144 	},
145 	{
146 		.peri_id = AT91C_ID_FLEXCOM0,
147 		.matrix = MATRIX_H32MX,
148 		.security_type = SECURITY_TYPE_PS,
149 	},
150 	{
151 		.peri_id = AT91C_ID_FLEXCOM1,
152 		.matrix = MATRIX_H32MX,
153 		.security_type = SECURITY_TYPE_PS,
154 	},
155 	{
156 		.peri_id = AT91C_ID_FLEXCOM2,
157 		.matrix = MATRIX_H32MX,
158 		.security_type = SECURITY_TYPE_PS,
159 	},
160 	{
161 		.peri_id = AT91C_ID_FLEXCOM3,
162 		.matrix = MATRIX_H32MX,
163 		.security_type = SECURITY_TYPE_PS,
164 	},
165 	{
166 		.peri_id = AT91C_ID_FLEXCOM4,
167 		.matrix = MATRIX_H32MX,
168 		.security_type = SECURITY_TYPE_PS,
169 	},
170 	{
171 		.peri_id = AT91C_ID_UART0,
172 		.matrix = MATRIX_H32MX,
173 		.security_type = SECURITY_TYPE_PS,
174 	},
175 	{
176 		.peri_id = AT91C_ID_UART1,
177 		.matrix = MATRIX_H32MX,
178 		.security_type = SECURITY_TYPE_PS,
179 	},
180 	{
181 		.peri_id = AT91C_ID_UART2,
182 		.matrix = MATRIX_H32MX,
183 		.security_type = SECURITY_TYPE_PS,
184 	},
185 	{
186 		.peri_id = AT91C_ID_UART3,
187 		.matrix = MATRIX_H32MX,
188 		.security_type = SECURITY_TYPE_PS,
189 	},
190 	{
191 		.peri_id = AT91C_ID_UART4,
192 		.matrix = MATRIX_H32MX,
193 		.security_type = SECURITY_TYPE_PS,
194 	},
195 	{
196 		.peri_id = AT91C_ID_TWI0,
197 		.matrix = MATRIX_H32MX,
198 		.security_type = SECURITY_TYPE_PS,
199 	},
200 	{
201 		.peri_id = AT91C_ID_TWI1,
202 		.matrix = MATRIX_H32MX,
203 		.security_type = SECURITY_TYPE_PS,
204 	},
205 	{
206 		.peri_id = AT91C_ID_SDMMC0,
207 		.matrix = MATRIX_H64MX,
208 		.security_type = SECURITY_TYPE_PS,
209 	},
210 	{
211 		.peri_id = AT91C_ID_SDMMC1,
212 		.matrix = MATRIX_H64MX,
213 		.security_type = SECURITY_TYPE_PS,
214 	},
215 	{
216 		.peri_id = AT91C_ID_SPI0,
217 		.matrix = MATRIX_H32MX,
218 		.security_type = SECURITY_TYPE_PS,
219 	},
220 	{
221 		.peri_id = AT91C_ID_SPI1,
222 		.matrix = MATRIX_H32MX,
223 		.security_type = SECURITY_TYPE_PS,
224 	},
225 	{
226 		.peri_id = AT91C_ID_TC0,
227 		.matrix = MATRIX_H32MX,
228 		.security_type = SECURITY_TYPE_PS,
229 	},
230 	{
231 		.peri_id = AT91C_ID_TC1,
232 		.matrix = MATRIX_H32MX,
233 		.security_type = SECURITY_TYPE_PS,
234 	},
235 	{
236 		.peri_id = AT91C_ID_PWM,
237 		.matrix = MATRIX_H32MX,
238 		.security_type = SECURITY_TYPE_PS,
239 	},
240 	{
241 		.peri_id = AT91C_ID_ADC,
242 		.matrix = MATRIX_H32MX,
243 		.security_type = SECURITY_TYPE_PS,
244 	},
245 	{
246 		.peri_id = AT91C_ID_UHPHS,
247 		.matrix = MATRIX_H32MX,
248 		.security_type = SECURITY_TYPE_PS,
249 	},
250 	{
251 		.peri_id = AT91C_ID_UDPHS,
252 		.matrix = MATRIX_H32MX,
253 		.security_type = SECURITY_TYPE_PS,
254 	},
255 	{
256 		.peri_id = AT91C_ID_SSC0,
257 		.matrix = MATRIX_H32MX,
258 		.security_type = SECURITY_TYPE_PS,
259 	},
260 	{
261 		.peri_id = AT91C_ID_SSC1,
262 		.matrix = MATRIX_H32MX,
263 		.security_type = SECURITY_TYPE_PS,
264 	},
265 	{
266 		.peri_id = AT91C_ID_LCDC,
267 		.matrix = MATRIX_H64MX,
268 		.security_type = SECURITY_TYPE_PS,
269 	},
270 	{
271 		.peri_id = AT91C_ID_ISI,
272 		.matrix = MATRIX_H64MX,
273 		.security_type = SECURITY_TYPE_PS,
274 	},
275 	{
276 		.peri_id = AT91C_ID_TRNG,
277 		.matrix = MATRIX_H32MX,
278 		.security_type = SECURITY_TYPE_PS,
279 	},
280 	{
281 		.peri_id = AT91C_ID_PDMIC,
282 		.matrix = MATRIX_H32MX,
283 		.security_type = SECURITY_TYPE_PS,
284 	},
285 	{
286 		.peri_id = AT91C_ID_IRQ,
287 		.matrix = MATRIX_H32MX,
288 		.security_type = SECURITY_TYPE_NS,
289 	},
290 	{
291 		.peri_id = AT91C_ID_SFC,
292 		.matrix = MATRIX_H32MX,
293 		.security_type = SECURITY_TYPE_PS,
294 	},
295 	{
296 		.peri_id = AT91C_ID_SECURAM,
297 		.matrix = MATRIX_H32MX,
298 		.security_type = SECURITY_TYPE_AS,
299 	},
300 	{
301 		.peri_id = AT91C_ID_QSPI0,
302 		.matrix = MATRIX_H64MX,
303 		.security_type = SECURITY_TYPE_PS,
304 	},
305 	{
306 		.peri_id = AT91C_ID_QSPI1,
307 		.matrix = MATRIX_H64MX,
308 		.security_type = SECURITY_TYPE_PS,
309 	},
310 	{
311 		.peri_id = AT91C_ID_I2SC0,
312 		.matrix = MATRIX_H32MX,
313 		.security_type = SECURITY_TYPE_PS,
314 	},
315 	{
316 		.peri_id = AT91C_ID_I2SC1,
317 		.matrix = MATRIX_H32MX,
318 		.security_type = SECURITY_TYPE_PS,
319 	},
320 	{
321 		.peri_id = AT91C_ID_CAN0_INT0,
322 		.matrix = MATRIX_H32MX,
323 		.security_type = SECURITY_TYPE_PS,
324 	},
325 	{
326 		.peri_id = AT91C_ID_CAN1_INT0,
327 		.matrix = MATRIX_H32MX,
328 		.security_type = SECURITY_TYPE_PS,
329 	},
330 	{
331 		.peri_id = AT91C_ID_CLASSD,
332 		.matrix = MATRIX_H32MX,
333 		.security_type = SECURITY_TYPE_PS,
334 	},
335 	{
336 		.peri_id = AT91C_ID_SFR,
337 		.matrix = MATRIX_H32MX,
338 		.security_type = SECURITY_TYPE_PS,
339 	},
340 	{
341 		.peri_id = AT91C_ID_SAIC,
342 		.matrix = MATRIX_H32MX,
343 		.security_type = SECURITY_TYPE_AS,
344 	},
345 	{
346 		.peri_id = AT91C_ID_AIC,
347 		.matrix = MATRIX_H32MX,
348 		.security_type = SECURITY_TYPE_NS,
349 	},
350 	{
351 		.peri_id = AT91C_ID_L2CC,
352 		.matrix = MATRIX_H64MX,
353 		.security_type = SECURITY_TYPE_PS,
354 	},
355 	{
356 		.peri_id = AT91C_ID_CAN0_INT1,
357 		.matrix = MATRIX_H32MX,
358 		.security_type = SECURITY_TYPE_PS,
359 	},
360 	{
361 		.peri_id = AT91C_ID_CAN1_INT1,
362 		.matrix = MATRIX_H32MX,
363 		.security_type = SECURITY_TYPE_PS,
364 	},
365 	{
366 		.peri_id = AT91C_ID_GMAC_Q1,
367 		.matrix = MATRIX_H32MX,
368 		.security_type = SECURITY_TYPE_PS,
369 	},
370 	{
371 		.peri_id = AT91C_ID_GMAC_Q2,
372 		.matrix = MATRIX_H32MX,
373 		.security_type = SECURITY_TYPE_PS,
374 	},
375 	{
376 		.peri_id = AT91C_ID_PIOB,
377 		.matrix = MATRIX_H32MX,
378 		.security_type = SECURITY_TYPE_AS,
379 	},
380 	{
381 		.peri_id = AT91C_ID_PIOC,
382 		.matrix = MATRIX_H32MX,
383 		.security_type = SECURITY_TYPE_AS,
384 	},
385 	{
386 		.peri_id = AT91C_ID_PIOD,
387 		.matrix = MATRIX_H32MX,
388 		.security_type = SECURITY_TYPE_AS,
389 	},
390 	{
391 		.peri_id = AT91C_ID_SDMMC0_TIMER,
392 		.matrix = MATRIX_H32MX,
393 		.security_type = SECURITY_TYPE_PS,
394 	},
395 	{
396 		.peri_id = AT91C_ID_SDMMC1_TIMER,
397 		.matrix = MATRIX_H32MX,
398 		.security_type = SECURITY_TYPE_PS,
399 	},
400 	{
401 		.peri_id = AT91C_ID_SYS,
402 		.matrix = MATRIX_H32MX,
403 		.security_type = SECURITY_TYPE_PS,
404 	},
405 	{
406 		.peri_id = AT91C_ID_ACC,
407 		.matrix = MATRIX_H32MX,
408 		.security_type = SECURITY_TYPE_PS,
409 	},
410 	{
411 		.peri_id = AT91C_ID_RXLP,
412 		.matrix = MATRIX_H32MX,
413 		.security_type = SECURITY_TYPE_PS,
414 	},
415 	{
416 		.peri_id = AT91C_ID_SFRBU,
417 		.matrix = MATRIX_H32MX,
418 		.security_type = SECURITY_TYPE_PS,
419 	},
420 	{
421 		.peri_id = AT91C_ID_CHIPID,
422 		.matrix = MATRIX_H32MX,
423 		.security_type = SECURITY_TYPE_PS,
424 	},
425 };
426 
matrix_write(unsigned int base,unsigned int offset,const unsigned int value)427 static void matrix_write(unsigned int base,
428 			 unsigned int offset,
429 			 const unsigned int value)
430 {
431 	io_write32(offset + base, value);
432 }
433 
matrix_read(int base,unsigned int offset)434 static unsigned int matrix_read(int base, unsigned int offset)
435 {
436 	return io_read32(offset + base);
437 }
438 
matrix_write_protect_enable(unsigned int matrix_base)439 void matrix_write_protect_enable(unsigned int matrix_base)
440 {
441 	matrix_write(matrix_base, MATRIX_WPMR,
442 		    (MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE));
443 }
444 
matrix_write_protect_disable(unsigned int matrix_base)445 void matrix_write_protect_disable(unsigned int matrix_base)
446 {
447 	matrix_write(matrix_base, MATRIX_WPMR, MATRIX_WPMR_WPKEY_PASSWD);
448 }
449 
matrix_configure_slave_security(unsigned int matrix_base,unsigned int slave,unsigned int srtop_setting,unsigned int srsplit_setting,unsigned int ssr_setting)450 void matrix_configure_slave_security(unsigned int matrix_base,
451 				     unsigned int slave,
452 				     unsigned int srtop_setting,
453 				     unsigned int srsplit_setting,
454 				     unsigned int ssr_setting)
455 {
456 	matrix_write(matrix_base, MATRIX_SSR(slave), ssr_setting);
457 	matrix_write(matrix_base, MATRIX_SRTSR(slave), srtop_setting);
458 	matrix_write(matrix_base, MATRIX_SASSR(slave), srsplit_setting);
459 }
460 
get_peri_security(unsigned int peri_id)461 static const struct peri_security *get_peri_security(unsigned int peri_id)
462 {
463 	unsigned int i;
464 
465 	for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) {
466 		if (peri_id == peri_security_array[i].peri_id)
467 			return &peri_security_array[i];
468 	}
469 
470 	return NULL;
471 }
472 
matrix_set_periph_world(unsigned int matrix,unsigned int peri_id,unsigned int world)473 static int matrix_set_periph_world(unsigned int matrix, unsigned int peri_id,
474 				   unsigned int world)
475 {
476 	unsigned int base;
477 	unsigned int spselr;
478 	unsigned int idx;
479 	unsigned int bit;
480 
481 	idx = peri_id / 32;
482 	if (idx > 3)
483 		return -1;
484 
485 	bit = (0x01 << (peri_id % 32));
486 
487 	if (matrix == MATRIX_H32MX)
488 		base = matrix32_base();
489 	else if (matrix == MATRIX_H64MX)
490 		base = matrix64_base();
491 	else
492 		return -1;
493 
494 	spselr = matrix_read(base, MATRIX_SPSELR(idx));
495 	if (world == WORLD_SECURE)
496 		spselr &= ~bit;
497 	else
498 		spselr |= bit;
499 	matrix_write(base, MATRIX_SPSELR(idx), spselr);
500 
501 	return 0;
502 }
503 
matrix_configure_periph_secure(unsigned int peri_id)504 int matrix_configure_periph_secure(unsigned int peri_id)
505 {
506 	const struct peri_security *psec = NULL;
507 
508 	psec = get_peri_security(peri_id);
509 	if (!psec)
510 		return -1;
511 
512 	return matrix_set_periph_world(psec->matrix, peri_id, WORLD_SECURE);
513 }
514 
matrix_configure_periph_non_secure(unsigned int * peri_id_array,unsigned int size)515 int matrix_configure_periph_non_secure(unsigned int *peri_id_array,
516 				       unsigned int size)
517 {
518 	unsigned int i;
519 	unsigned int *peri_id_p;
520 	unsigned int matrix;
521 	unsigned int peri_id;
522 	const struct peri_security *peripheral_sec;
523 	int ret;
524 
525 	if (!peri_id_array || !size)
526 		return -1;
527 
528 	peri_id_p = peri_id_array;
529 	for (i = 0; i < size; i++) {
530 		peripheral_sec = get_peri_security(*peri_id_p);
531 		if (!peripheral_sec)
532 			return -1;
533 
534 		if (peripheral_sec->security_type != SECURITY_TYPE_PS)
535 			return -1;
536 
537 		matrix = peripheral_sec->matrix;
538 		peri_id = *peri_id_p;
539 		ret = matrix_set_periph_world(matrix, peri_id,
540 					      WORLD_NON_SECURE);
541 		if (ret)
542 			return -1;
543 
544 		peri_id_p++;
545 	}
546 
547 	return 0;
548 }
549