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