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