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