xref: /optee_os/core/arch/arm/plat-sam/matrix.c (revision cb5b170123a843e4a9ad4668900d8a99d9b0e362)
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 struct peri_security {
46 	unsigned int peri_id;
47 	unsigned int matrix;
48 	unsigned int security_type;
49 };
50 
51 static const struct peri_security peri_security_array[] = {
52 	{
53 		.peri_id = AT91C_ID_PMC,
54 		.matrix = MATRIX_H64MX,
55 		.security_type = SECURITY_TYPE_PS,
56 	},
57 	{
58 		.peri_id = AT91C_ID_ARM,
59 		.matrix = MATRIX_H64MX,
60 		.security_type = SECURITY_TYPE_PS,
61 	},
62 	{
63 		.peri_id = AT91C_ID_PIT,
64 		.matrix = MATRIX_H32MX,
65 		.security_type = SECURITY_TYPE_PS,
66 	},
67 	{
68 		.peri_id = AT91C_ID_WDT,
69 		.matrix = MATRIX_H32MX,
70 		.security_type = SECURITY_TYPE_PS,
71 	},
72 	{
73 		.peri_id = AT91C_ID_GMAC,
74 		.matrix = MATRIX_H32MX,
75 		.security_type = SECURITY_TYPE_PS,
76 	},
77 	{
78 		.peri_id = AT91C_ID_XDMAC0,
79 		.matrix = MATRIX_H64MX,
80 		.security_type = SECURITY_TYPE_PS,
81 	},
82 	{
83 		.peri_id = AT91C_ID_XDMAC1,
84 		.matrix = MATRIX_H64MX,
85 		.security_type = SECURITY_TYPE_PS,
86 	},
87 	{
88 		.peri_id = AT91C_ID_ICM,
89 		.matrix = MATRIX_H32MX,
90 		.security_type = SECURITY_TYPE_PS,
91 	},
92 	{
93 		.peri_id = AT91C_ID_AES,
94 		.matrix = MATRIX_H64MX,
95 		.security_type = SECURITY_TYPE_PS,
96 	},
97 	{
98 		.peri_id = AT91C_ID_AESB,
99 		.matrix = MATRIX_H64MX,
100 		.security_type = SECURITY_TYPE_PS,
101 	},
102 	{
103 		.peri_id = AT91C_ID_TDES,
104 		.matrix = MATRIX_H32MX,
105 		.security_type = SECURITY_TYPE_PS,
106 	},
107 	{
108 		.peri_id = AT91C_ID_SHA,
109 		.matrix = MATRIX_H64MX,
110 		.security_type = SECURITY_TYPE_PS,
111 	},
112 	{
113 		.peri_id = AT91C_ID_MPDDRC,
114 		.matrix = MATRIX_H64MX,
115 		.security_type = SECURITY_TYPE_PS,
116 	},
117 	{
118 		.peri_id = AT91C_ID_MATRIX1,
119 		.matrix = MATRIX_H32MX,
120 		.security_type = SECURITY_TYPE_AS,
121 	},
122 	{
123 		.peri_id = AT91C_ID_MATRIX0,
124 		.matrix = MATRIX_H64MX,
125 		.security_type = SECURITY_TYPE_AS,
126 	},
127 	{
128 		.peri_id = AT91C_ID_SECUMOD,
129 		.matrix = MATRIX_H32MX,
130 		.security_type = SECURITY_TYPE_AS,
131 	},
132 	{
133 		.peri_id = AT91C_ID_HSMC,
134 		.matrix = MATRIX_H32MX,
135 		.security_type = SECURITY_TYPE_PS,
136 	},
137 	{
138 		.peri_id = AT91C_ID_PIOA,
139 		.matrix = MATRIX_H32MX,
140 		.security_type = SECURITY_TYPE_AS,
141 	},
142 	{
143 		.peri_id = AT91C_ID_FLEXCOM0,
144 		.matrix = MATRIX_H32MX,
145 		.security_type = SECURITY_TYPE_PS,
146 	},
147 	{
148 		.peri_id = AT91C_ID_FLEXCOM1,
149 		.matrix = MATRIX_H32MX,
150 		.security_type = SECURITY_TYPE_PS,
151 	},
152 	{
153 		.peri_id = AT91C_ID_FLEXCOM2,
154 		.matrix = MATRIX_H32MX,
155 		.security_type = SECURITY_TYPE_PS,
156 	},
157 	{
158 		.peri_id = AT91C_ID_FLEXCOM3,
159 		.matrix = MATRIX_H32MX,
160 		.security_type = SECURITY_TYPE_PS,
161 	},
162 	{
163 		.peri_id = AT91C_ID_FLEXCOM4,
164 		.matrix = MATRIX_H32MX,
165 		.security_type = SECURITY_TYPE_PS,
166 	},
167 	{
168 		.peri_id = AT91C_ID_UART0,
169 		.matrix = MATRIX_H32MX,
170 		.security_type = SECURITY_TYPE_PS,
171 	},
172 	{
173 		.peri_id = AT91C_ID_UART1,
174 		.matrix = MATRIX_H32MX,
175 		.security_type = SECURITY_TYPE_PS,
176 	},
177 	{
178 		.peri_id = AT91C_ID_UART2,
179 		.matrix = MATRIX_H32MX,
180 		.security_type = SECURITY_TYPE_PS,
181 	},
182 	{
183 		.peri_id = AT91C_ID_UART3,
184 		.matrix = MATRIX_H32MX,
185 		.security_type = SECURITY_TYPE_PS,
186 	},
187 	{
188 		.peri_id = AT91C_ID_UART4,
189 		.matrix = MATRIX_H32MX,
190 		.security_type = SECURITY_TYPE_PS,
191 	},
192 	{
193 		.peri_id = AT91C_ID_TWI0,
194 		.matrix = MATRIX_H32MX,
195 		.security_type = SECURITY_TYPE_PS,
196 	},
197 	{
198 		.peri_id = AT91C_ID_TWI1,
199 		.matrix = MATRIX_H32MX,
200 		.security_type = SECURITY_TYPE_PS,
201 	},
202 	{
203 		.peri_id = AT91C_ID_SDMMC0,
204 		.matrix = MATRIX_H64MX,
205 		.security_type = SECURITY_TYPE_PS,
206 	},
207 	{
208 		.peri_id = AT91C_ID_SDMMC1,
209 		.matrix = MATRIX_H64MX,
210 		.security_type = SECURITY_TYPE_PS,
211 	},
212 	{
213 		.peri_id = AT91C_ID_SPI0,
214 		.matrix = MATRIX_H32MX,
215 		.security_type = SECURITY_TYPE_PS,
216 	},
217 	{
218 		.peri_id = AT91C_ID_SPI1,
219 		.matrix = MATRIX_H32MX,
220 		.security_type = SECURITY_TYPE_PS,
221 	},
222 	{
223 		.peri_id = AT91C_ID_TC0,
224 		.matrix = MATRIX_H32MX,
225 		.security_type = SECURITY_TYPE_PS,
226 	},
227 	{
228 		.peri_id = AT91C_ID_TC1,
229 		.matrix = MATRIX_H32MX,
230 		.security_type = SECURITY_TYPE_PS,
231 	},
232 	{
233 		.peri_id = AT91C_ID_PWM,
234 		.matrix = MATRIX_H32MX,
235 		.security_type = SECURITY_TYPE_PS,
236 	},
237 	{
238 		.peri_id = AT91C_ID_ADC,
239 		.matrix = MATRIX_H32MX,
240 		.security_type = SECURITY_TYPE_PS,
241 	},
242 	{
243 		.peri_id = AT91C_ID_UHPHS,
244 		.matrix = MATRIX_H32MX,
245 		.security_type = SECURITY_TYPE_PS,
246 	},
247 	{
248 		.peri_id = AT91C_ID_UDPHS,
249 		.matrix = MATRIX_H32MX,
250 		.security_type = SECURITY_TYPE_PS,
251 	},
252 	{
253 		.peri_id = AT91C_ID_SSC0,
254 		.matrix = MATRIX_H32MX,
255 		.security_type = SECURITY_TYPE_PS,
256 	},
257 	{
258 		.peri_id = AT91C_ID_SSC1,
259 		.matrix = MATRIX_H32MX,
260 		.security_type = SECURITY_TYPE_PS,
261 	},
262 	{
263 		.peri_id = AT91C_ID_LCDC,
264 		.matrix = MATRIX_H64MX,
265 		.security_type = SECURITY_TYPE_PS,
266 	},
267 	{
268 		.peri_id = AT91C_ID_ISI,
269 		.matrix = MATRIX_H64MX,
270 		.security_type = SECURITY_TYPE_PS,
271 	},
272 	{
273 		.peri_id = AT91C_ID_TRNG,
274 		.matrix = MATRIX_H32MX,
275 		.security_type = SECURITY_TYPE_PS,
276 	},
277 	{
278 		.peri_id = AT91C_ID_PDMIC,
279 		.matrix = MATRIX_H32MX,
280 		.security_type = SECURITY_TYPE_PS,
281 	},
282 	{
283 		.peri_id = AT91C_ID_IRQ,
284 		.matrix = MATRIX_H32MX,
285 		.security_type = SECURITY_TYPE_NS,
286 	},
287 	{
288 		.peri_id = AT91C_ID_SFC,
289 		.matrix = MATRIX_H32MX,
290 		.security_type = SECURITY_TYPE_PS,
291 	},
292 	{
293 		.peri_id = AT91C_ID_SECURAM,
294 		.matrix = MATRIX_H32MX,
295 		.security_type = SECURITY_TYPE_AS,
296 	},
297 	{
298 		.peri_id = AT91C_ID_QSPI0,
299 		.matrix = MATRIX_H64MX,
300 		.security_type = SECURITY_TYPE_PS,
301 	},
302 	{
303 		.peri_id = AT91C_ID_QSPI1,
304 		.matrix = MATRIX_H64MX,
305 		.security_type = SECURITY_TYPE_PS,
306 	},
307 	{
308 		.peri_id = AT91C_ID_I2SC0,
309 		.matrix = MATRIX_H32MX,
310 		.security_type = SECURITY_TYPE_PS,
311 	},
312 	{
313 		.peri_id = AT91C_ID_I2SC1,
314 		.matrix = MATRIX_H32MX,
315 		.security_type = SECURITY_TYPE_PS,
316 	},
317 	{
318 		.peri_id = AT91C_ID_CAN0_INT0,
319 		.matrix = MATRIX_H32MX,
320 		.security_type = SECURITY_TYPE_PS,
321 	},
322 	{
323 		.peri_id = AT91C_ID_CAN1_INT0,
324 		.matrix = MATRIX_H32MX,
325 		.security_type = SECURITY_TYPE_PS,
326 	},
327 	{
328 		.peri_id = AT91C_ID_CLASSD,
329 		.matrix = MATRIX_H32MX,
330 		.security_type = SECURITY_TYPE_PS,
331 	},
332 	{
333 		.peri_id = AT91C_ID_SFR,
334 		.matrix = MATRIX_H32MX,
335 		.security_type = SECURITY_TYPE_PS,
336 	},
337 	{
338 		.peri_id = AT91C_ID_SAIC,
339 		.matrix = MATRIX_H32MX,
340 		.security_type = SECURITY_TYPE_AS,
341 	},
342 	{
343 		.peri_id = AT91C_ID_AIC,
344 		.matrix = MATRIX_H32MX,
345 		.security_type = SECURITY_TYPE_NS,
346 	},
347 	{
348 		.peri_id = AT91C_ID_L2CC,
349 		.matrix = MATRIX_H64MX,
350 		.security_type = SECURITY_TYPE_PS,
351 	},
352 	{
353 		.peri_id = AT91C_ID_CAN0_INT1,
354 		.matrix = MATRIX_H32MX,
355 		.security_type = SECURITY_TYPE_PS,
356 	},
357 	{
358 		.peri_id = AT91C_ID_CAN1_INT1,
359 		.matrix = MATRIX_H32MX,
360 		.security_type = SECURITY_TYPE_PS,
361 	},
362 	{
363 		.peri_id = AT91C_ID_GMAC_Q1,
364 		.matrix = MATRIX_H32MX,
365 		.security_type = SECURITY_TYPE_PS,
366 	},
367 	{
368 		.peri_id = AT91C_ID_GMAC_Q2,
369 		.matrix = MATRIX_H32MX,
370 		.security_type = SECURITY_TYPE_PS,
371 	},
372 	{
373 		.peri_id = AT91C_ID_PIOB,
374 		.matrix = MATRIX_H32MX,
375 		.security_type = SECURITY_TYPE_AS,
376 	},
377 	{
378 		.peri_id = AT91C_ID_PIOC,
379 		.matrix = MATRIX_H32MX,
380 		.security_type = SECURITY_TYPE_AS,
381 	},
382 	{
383 		.peri_id = AT91C_ID_PIOD,
384 		.matrix = MATRIX_H32MX,
385 		.security_type = SECURITY_TYPE_AS,
386 	},
387 	{
388 		.peri_id = AT91C_ID_SDMMC0_TIMER,
389 		.matrix = MATRIX_H32MX,
390 		.security_type = SECURITY_TYPE_PS,
391 	},
392 	{
393 		.peri_id = AT91C_ID_SDMMC1_TIMER,
394 		.matrix = MATRIX_H32MX,
395 		.security_type = SECURITY_TYPE_PS,
396 	},
397 	{
398 		.peri_id = AT91C_ID_SYS,
399 		.matrix = MATRIX_H32MX,
400 		.security_type = SECURITY_TYPE_PS,
401 	},
402 	{
403 		.peri_id = AT91C_ID_ACC,
404 		.matrix = MATRIX_H32MX,
405 		.security_type = SECURITY_TYPE_PS,
406 	},
407 	{
408 		.peri_id = AT91C_ID_RXLP,
409 		.matrix = MATRIX_H32MX,
410 		.security_type = SECURITY_TYPE_PS,
411 	},
412 	{
413 		.peri_id = AT91C_ID_SFRBU,
414 		.matrix = MATRIX_H32MX,
415 		.security_type = SECURITY_TYPE_PS,
416 	},
417 	{
418 		.peri_id = AT91C_ID_CHIPID,
419 		.matrix = MATRIX_H32MX,
420 		.security_type = SECURITY_TYPE_PS,
421 	},
422 };
423 
424 static void matrix_write(unsigned int base,
425 			 unsigned int offset,
426 			 const unsigned int value)
427 {
428 	io_write32(offset + base, value);
429 }
430 
431 static unsigned int matrix_read(int base, unsigned int offset)
432 {
433 	return io_read32(offset + base);
434 }
435 
436 void matrix_write_protect_enable(unsigned int matrix_base)
437 {
438 	matrix_write(matrix_base, MATRIX_WPMR,
439 		    (MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE));
440 }
441 
442 void matrix_write_protect_disable(unsigned int matrix_base)
443 {
444 	matrix_write(matrix_base, MATRIX_WPMR, MATRIX_WPMR_WPKEY_PASSWD);
445 }
446 
447 void matrix_configure_slave_security(unsigned int matrix_base,
448 				     unsigned int slave,
449 				     unsigned int srtop_setting,
450 				     unsigned int srsplit_setting,
451 				     unsigned int ssr_setting)
452 {
453 	matrix_write(matrix_base, MATRIX_SSR(slave), ssr_setting);
454 	matrix_write(matrix_base, MATRIX_SRTSR(slave), srtop_setting);
455 	matrix_write(matrix_base, MATRIX_SASSR(slave), srsplit_setting);
456 }
457 
458 static const struct peri_security *get_peri_security(unsigned int peri_id)
459 {
460 	unsigned int i;
461 
462 	for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) {
463 		if (peri_id == peri_security_array[i].peri_id)
464 			return &peri_security_array[i];
465 	}
466 
467 	return NULL;
468 }
469 
470 static int matrix_set_peri_security(unsigned int matrix, unsigned int peri_id)
471 {
472 	unsigned int base;
473 	unsigned int spselr;
474 	unsigned int idx;
475 	unsigned int bit;
476 
477 	idx = peri_id / 32;
478 	if (idx > 3)
479 		return -1;
480 
481 	bit = (0x01 << (peri_id % 32));
482 
483 	if (matrix == MATRIX_H32MX)
484 		base = matrix32_base();
485 	else if (matrix == MATRIX_H64MX)
486 		base = matrix64_base();
487 	else
488 		return -1;
489 
490 	spselr = matrix_read(base, MATRIX_SPSELR(idx));
491 	spselr |= bit;
492 	matrix_write(base, MATRIX_SPSELR(idx), spselr);
493 
494 	return 0;
495 }
496 
497 int matrix_configure_peri_security(unsigned int *peri_id_array,
498 				   unsigned int size)
499 {
500 	unsigned int i;
501 	unsigned int *peri_id_p;
502 	unsigned int matrix;
503 	unsigned int peri_id;
504 	const struct peri_security *peripheral_sec;
505 	int ret;
506 
507 	if (!peri_id_array || !size)
508 		return -1;
509 
510 	peri_id_p = peri_id_array;
511 	for (i = 0; i < size; i++) {
512 		peripheral_sec = get_peri_security(*peri_id_p);
513 		if (!peripheral_sec)
514 			return -1;
515 
516 		if (peripheral_sec->security_type != SECURITY_TYPE_PS)
517 			return -1;
518 
519 		matrix = peripheral_sec->matrix;
520 		peri_id = *peri_id_p;
521 		ret = matrix_set_peri_security(matrix, peri_id);
522 		if (ret)
523 			return -1;
524 
525 		peri_id_p++;
526 	}
527 
528 	return 0;
529 }
530