xref: /optee_os/core/arch/arm/plat-sam/matrix.c (revision 8e81e2f5366a971afdd2ac47fb8529d1def5feb0)
1 /*
2  * Copyright (c) 2013, Atmel Corporation
3  * Copyright (c) 2017, Timesys Corporation
4  *
5  * All rights reserved.
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  * - Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the disclaimer below.
12  *
13  * Atmel's name may not be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
19  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include <arm32.h>
28 #include <io.h>
29 #include <sama5d2.h>
30 #include <platform_config.h>
31 #include <stdint.h>
32 #include <matrix.h>
33 #include <tz_matrix.h>
34 #include <trace.h>
35 
36 #define MATRIX_AXIMX	1
37 #define MATRIX_H64MX	2
38 #define MATRIX_H32MX	3
39 
40 #define SECURITY_TYPE_AS	1
41 #define SECURITY_TYPE_NS	2
42 #define SECURITY_TYPE_PS	3
43 
44 struct peri_security {
45 	unsigned int peri_id;
46 	unsigned int matrix;
47 	unsigned int security_type;
48 };
49 
50 static const struct peri_security peri_security_array[] = {
51 	/*
52 	 * AT91C_ID_1 - This is a undocumented bit in the datasheet.
53 	 * However needs to be set for Linux to boot in "normal world"
54 	 */
55 	{
56 		.peri_id = AT91C_ID_1,
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 
427 static void matrix_write(unsigned int base,
428 			 unsigned int offset,
429 			 const unsigned int value)
430 {
431 	write32(value, offset + base);
432 }
433 
434 static unsigned int matrix_read(int base, unsigned int offset)
435 {
436 	return read32(offset + base);
437 }
438 
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 
445 void matrix_write_protect_disable(unsigned int matrix_base)
446 {
447 	matrix_write(matrix_base, MATRIX_WPMR, MATRIX_WPMR_WPKEY_PASSWD);
448 }
449 
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 
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 
473 static int matrix_set_peri_security(unsigned int matrix, unsigned int peri_id)
474 {
475 	unsigned int base;
476 	unsigned int spselr;
477 	unsigned int idx;
478 	unsigned int bit;
479 
480 	idx = peri_id / 32;
481 	if (idx > 3)
482 		return -1;
483 
484 	bit = (0x01 << (peri_id % 32));
485 
486 	/* The Peripheral ID to SPSELR register bit mapping breaks at ID 73 */
487 	if (peri_id > AT91C_ID_SDMMC1_TIMER)
488 		bit = bit >> 1;
489 
490 	if (matrix == MATRIX_H32MX)
491 		base = matrix32_base();
492 	else if (matrix == MATRIX_H64MX)
493 		base = matrix64_base();
494 	else
495 		return -1;
496 
497 	spselr = matrix_read(base, MATRIX_SPSELR(idx));
498 	spselr |= bit;
499 	matrix_write(base, MATRIX_SPSELR(idx), spselr);
500 
501 	return 0;
502 }
503 
504 int matrix_configure_peri_security(unsigned int *peri_id_array,
505 				   unsigned int size)
506 {
507 	unsigned int i;
508 	unsigned int *peri_id_p;
509 	unsigned int matrix;
510 	unsigned int peri_id;
511 	const struct peri_security *peripheral_sec;
512 	int ret;
513 
514 	if (!peri_id_array || !size)
515 		return -1;
516 
517 	peri_id_p = peri_id_array;
518 	for (i = 0; i < size; i++) {
519 		peripheral_sec = get_peri_security(*peri_id_p);
520 		if (!peripheral_sec)
521 			return -1;
522 
523 		if (peripheral_sec->security_type != SECURITY_TYPE_PS)
524 			return -1;
525 
526 		matrix = peripheral_sec->matrix;
527 		peri_id = *peri_id_p;
528 		ret = matrix_set_peri_security(matrix, peri_id);
529 		if (ret)
530 			return -1;
531 
532 		peri_id_p++;
533 	}
534 
535 	return 0;
536 }
537