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