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