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