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