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