1 /* 2 * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. 3 * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <stdbool.h> 9 #include <string.h> 10 11 #include <common/debug.h> 12 #include <drivers/generic_delay_timer.h> 13 #include <lib/mmio.h> 14 #include <lib/smccc.h> 15 #include <lib/xlat_tables/xlat_tables.h> 16 #include <plat/common/platform.h> 17 #include <services/arm_arch_svc.h> 18 19 #include <plat_ipi.h> 20 #include <plat_private.h> 21 #include <plat_startup.h> 22 23 #include "zynqmp_pm_api_sys.h" 24 25 /* 26 * Table of regions to map using the MMU. 27 * This doesn't include TZRAM as the 'mem_layout' argument passed to 28 * configure_mmu_elx() will give the available subset of that, 29 */ 30 const mmap_region_t plat_arm_mmap[] = { 31 { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 32 { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 33 { CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 34 {0} 35 }; 36 37 static uint32_t zynqmp_get_silicon_ver(void) 38 { 39 static unsigned int ver; 40 41 if (!ver) { 42 ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + 43 ZYNQMP_CSU_VERSION_OFFSET); 44 ver &= ZYNQMP_SILICON_VER_MASK; 45 ver >>= ZYNQMP_SILICON_VER_SHIFT; 46 } 47 48 return ver; 49 } 50 51 uint32_t zynqmp_get_uart_clk(void) 52 { 53 unsigned int ver = zynqmp_get_silicon_ver(); 54 55 if (ver == ZYNQMP_CSU_VERSION_QEMU) { 56 return 133000000; 57 } else { 58 return 100000000; 59 } 60 } 61 62 #if LOG_LEVEL >= LOG_LEVEL_NOTICE 63 static const struct { 64 uint8_t id; 65 bool evexists; 66 uint16_t ver; 67 char *name; 68 } __packed zynqmp_devices[] = { 69 { 70 .id = 0x10, 71 .name = "XCZU3EG", 72 }, 73 { 74 .id = 0x10, 75 .ver = 0x2c, 76 .name = "XCZU3CG", 77 }, 78 { 79 .id = 0x11, 80 .name = "XCZU2EG", 81 }, 82 { 83 .id = 0x11, 84 .ver = 0x2c, 85 .name = "XCZU2CG", 86 }, 87 { 88 .id = 0x20, 89 .name = "XCZU5EV", 90 .evexists = true, 91 }, 92 { 93 .id = 0x20, 94 .ver = 0x100, 95 .name = "XCZU5EG", 96 .evexists = true, 97 }, 98 { 99 .id = 0x20, 100 .ver = 0x12c, 101 .name = "XCZU5CG", 102 }, 103 { 104 .id = 0x21, 105 .name = "XCZU4EV", 106 .evexists = true, 107 }, 108 { 109 .id = 0x21, 110 .ver = 0x100, 111 .name = "XCZU4EG", 112 .evexists = true, 113 }, 114 { 115 .id = 0x21, 116 .ver = 0x12c, 117 .name = "XCZU4CG", 118 }, 119 { 120 .id = 0x30, 121 .name = "XCZU7EV", 122 .evexists = true, 123 }, 124 { 125 .id = 0x30, 126 .ver = 0x100, 127 .name = "XCZU7EG", 128 .evexists = true, 129 }, 130 { 131 .id = 0x30, 132 .ver = 0x12c, 133 .name = "XCZU7CG", 134 }, 135 { 136 .id = 0x38, 137 .name = "XCZU9EG", 138 }, 139 { 140 .id = 0x38, 141 .ver = 0x2c, 142 .name = "XCZU9CG", 143 }, 144 { 145 .id = 0x39, 146 .name = "XCZU6EG", 147 }, 148 { 149 .id = 0x39, 150 .ver = 0x2c, 151 .name = "XCZU6CG", 152 }, 153 { 154 .id = 0x40, 155 .name = "XCZU11EG", 156 }, 157 { 158 .id = 0x50, 159 .name = "XCZU15EG", 160 }, 161 { 162 .id = 0x58, 163 .name = "XCZU19EG", 164 }, 165 { 166 .id = 0x59, 167 .name = "XCZU17EG", 168 }, 169 { 170 .id = 0x60, 171 .name = "XCZU28DR", 172 }, 173 { 174 .id = 0x61, 175 .name = "XCZU21DR", 176 }, 177 { 178 .id = 0x62, 179 .name = "XCZU29DR", 180 }, 181 { 182 .id = 0x63, 183 .name = "XCZU23DR", 184 }, 185 { 186 .id = 0x64, 187 .name = "XCZU27DR", 188 }, 189 { 190 .id = 0x65, 191 .name = "XCZU25DR", 192 }, 193 { 194 .id = 0x66, 195 .name = "XCZU39DR", 196 }, 197 { 198 .id = 0x7d, 199 .name = "XCZU43DR", 200 }, 201 { 202 .id = 0x78, 203 .name = "XCZU46DR", 204 }, 205 { 206 .id = 0x7f, 207 .name = "XCZU47DR", 208 }, 209 { 210 .id = 0x7b, 211 .name = "XCZU48DR", 212 }, 213 { 214 .id = 0x7e, 215 .name = "XCZU49DR", 216 }, 217 }; 218 219 #define ZYNQMP_PL_STATUS_BIT 9 220 #define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) 221 #define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) 222 223 #define SILICON_ID_XCK24 0x4712093U 224 #define SILICON_ID_XCK26 0x4724093U 225 226 static char *zynqmp_get_silicon_idcode_name(void) 227 { 228 uint32_t id, ver, chipid[2]; 229 size_t i, j, len; 230 const char *name = "EG/EV"; 231 232 #ifdef IMAGE_BL32 233 /* 234 * For BL32, get the chip id info directly by reading corresponding 235 * registers instead of making pm call. This has limitation 236 * that these registers should be configured to have access 237 * from APU which is default case. 238 */ 239 chipid[0] = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 240 chipid[1] = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET); 241 #else 242 if (pm_get_chipid(chipid) != PM_RET_SUCCESS) { 243 return "XCZUUNKN"; 244 } 245 #endif 246 247 id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 248 ZYNQMP_CSU_IDCODE_SVD_MASK); 249 id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 250 ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT; 251 252 for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 253 if (zynqmp_devices[i].id == id && 254 zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK)) { 255 break; 256 } 257 } 258 259 if (i >= ARRAY_SIZE(zynqmp_devices)) { 260 switch (chipid[0]) { 261 case SILICON_ID_XCK24: 262 return "XCK24"; 263 case SILICON_ID_XCK26: 264 return "XCK26"; 265 default: 266 return "XCZUUNKN"; 267 } 268 } 269 270 if (!zynqmp_devices[i].evexists) { 271 return zynqmp_devices[i].name; 272 } 273 274 if ((ver & ZYNQMP_PL_STATUS_MASK) != 0U) { 275 return zynqmp_devices[i].name; 276 } 277 278 len = strlen(zynqmp_devices[i].name) - 2; 279 for (j = 0; j < strlen(name); j++) { 280 zynqmp_devices[i].name[len] = name[j]; 281 len++; 282 } 283 zynqmp_devices[i].name[len] = '\0'; 284 285 return zynqmp_devices[i].name; 286 } 287 288 static unsigned int zynqmp_get_rtl_ver(void) 289 { 290 uint32_t ver; 291 292 ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 293 ver &= ZYNQMP_RTL_VER_MASK; 294 ver >>= ZYNQMP_RTL_VER_SHIFT; 295 296 return ver; 297 } 298 299 static char *zynqmp_print_silicon_idcode(void) 300 { 301 uint32_t id, maskid, tmp; 302 303 id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 304 305 tmp = id; 306 tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | 307 ZYNQMP_CSU_IDCODE_FAMILY_MASK; 308 maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | 309 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT; 310 if (tmp != maskid) { 311 ERROR("Incorrect IDCODE 0x%x, maskid 0x%x\n", id, maskid); 312 return "UNKN"; 313 } 314 VERBOSE("IDCODE 0x%x\n", id); 315 return zynqmp_get_silicon_idcode_name(); 316 } 317 318 int32_t plat_is_smccc_feature_available(u_register_t fid) 319 { 320 switch (fid) { 321 case SMCCC_ARCH_SOC_ID: 322 return SMC_ARCH_CALL_SUCCESS; 323 default: 324 return SMC_ARCH_CALL_NOT_SUPPORTED; 325 } 326 327 return SMC_ARCH_CALL_NOT_SUPPORTED; 328 } 329 330 int32_t plat_get_soc_version(void) 331 { 332 uint32_t chip_id = zynqmp_get_silicon_ver(); 333 uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID); 334 335 return (int32_t)(manfid | (chip_id & 0xFFFF)); 336 } 337 338 int32_t plat_get_soc_revision(void) 339 { 340 return mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 341 } 342 343 static uint32_t zynqmp_get_ps_ver(void) 344 { 345 uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 346 347 ver &= ZYNQMP_PS_VER_MASK; 348 ver >>= ZYNQMP_PS_VER_SHIFT; 349 350 return ver + 1U; 351 } 352 353 static void zynqmp_print_platform_name(void) 354 { 355 uint32_t ver = zynqmp_get_silicon_ver(); 356 uint32_t rtl = zynqmp_get_rtl_ver(); 357 char *label = "Unknown"; 358 359 switch (ver) { 360 case ZYNQMP_CSU_VERSION_QEMU: 361 label = "QEMU"; 362 break; 363 case ZYNQMP_CSU_VERSION_SILICON: 364 label = "silicon"; 365 break; 366 default: 367 /* Do nothing in default case */ 368 break; 369 } 370 371 VERBOSE("TF-A running on %s/%s at 0x%x\n", 372 zynqmp_print_silicon_idcode(), label, BL31_BASE); 373 VERBOSE("TF-A running on v%d/RTL%d.%d\n", 374 zynqmp_get_ps_ver(), (rtl & 0xf0) >> 4, rtl & 0xf); 375 } 376 #else 377 static inline void zynqmp_print_platform_name(void) { } 378 #endif 379 380 uint32_t zynqmp_get_bootmode(void) 381 { 382 uint32_t r; 383 unsigned int ret; 384 385 ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r); 386 387 if (ret != PM_RET_SUCCESS) { 388 r = mmio_read_32(CRL_APB_BOOT_MODE_USER); 389 } 390 391 return r & CRL_APB_BOOT_MODE_MASK; 392 } 393 394 void zynqmp_config_setup(void) 395 { 396 uint64_t counter_freq; 397 398 /* Configure IPI data for ZynqMP */ 399 zynqmp_ipi_config_table_init(); 400 401 zynqmp_print_platform_name(); 402 403 /* Configure counter frequency */ 404 counter_freq = read_cntfrq_el0(); 405 if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) { 406 write_cntfrq_el0(plat_get_syscnt_freq2()); 407 } 408 409 generic_delay_timer_init(); 410 } 411 412 uint32_t plat_get_syscnt_freq2(void) 413 { 414 uint32_t ver = zynqmp_get_silicon_ver(); 415 416 if (ver == ZYNQMP_CSU_VERSION_QEMU) { 417 return 65000000; 418 } else { 419 return mmio_read_32(IOU_SCNTRS_BASEFREQ); 420 } 421 } 422