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 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 434 static unsigned int matrix_read(int base, unsigned int offset) 435 { 436 return io_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_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 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 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