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 if (pm_get_chipid(chipid) != PM_RET_SUCCESS) { 233 return "XCZUUNKN"; 234 } 235 236 id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 237 ZYNQMP_CSU_IDCODE_SVD_MASK); 238 id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 239 ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT; 240 241 for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 242 if (zynqmp_devices[i].id == id && 243 zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK)) { 244 break; 245 } 246 } 247 248 if (i >= ARRAY_SIZE(zynqmp_devices)) { 249 switch (chipid[0]) { 250 case SILICON_ID_XCK24: 251 return "XCK24"; 252 case SILICON_ID_XCK26: 253 return "XCK26"; 254 default: 255 return "XCZUUNKN"; 256 } 257 } 258 259 if (!zynqmp_devices[i].evexists) { 260 return zynqmp_devices[i].name; 261 } 262 263 if ((ver & ZYNQMP_PL_STATUS_MASK) != 0U) { 264 return zynqmp_devices[i].name; 265 } 266 267 len = strlen(zynqmp_devices[i].name) - 2; 268 for (j = 0; j < strlen(name); j++) { 269 zynqmp_devices[i].name[len] = name[j]; 270 len++; 271 } 272 zynqmp_devices[i].name[len] = '\0'; 273 274 return zynqmp_devices[i].name; 275 } 276 277 static unsigned int zynqmp_get_rtl_ver(void) 278 { 279 uint32_t ver; 280 281 ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 282 ver &= ZYNQMP_RTL_VER_MASK; 283 ver >>= ZYNQMP_RTL_VER_SHIFT; 284 285 return ver; 286 } 287 288 static char *zynqmp_print_silicon_idcode(void) 289 { 290 uint32_t id, maskid, tmp; 291 292 id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 293 294 tmp = id; 295 tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | 296 ZYNQMP_CSU_IDCODE_FAMILY_MASK; 297 maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | 298 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT; 299 if (tmp != maskid) { 300 ERROR("Incorrect IDCODE 0x%x, maskid 0x%x\n", id, maskid); 301 return "UNKN"; 302 } 303 VERBOSE("IDCODE 0x%x\n", id); 304 return zynqmp_get_silicon_idcode_name(); 305 } 306 307 int32_t plat_is_smccc_feature_available(u_register_t fid) 308 { 309 switch (fid) { 310 case SMCCC_ARCH_SOC_ID: 311 return SMC_ARCH_CALL_SUCCESS; 312 default: 313 return SMC_ARCH_CALL_NOT_SUPPORTED; 314 } 315 316 return SMC_ARCH_CALL_NOT_SUPPORTED; 317 } 318 319 int32_t plat_get_soc_version(void) 320 { 321 uint32_t chip_id = zynqmp_get_silicon_ver(); 322 uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID); 323 324 return (int32_t)(manfid | (chip_id & 0xFFFF)); 325 } 326 327 int32_t plat_get_soc_revision(void) 328 { 329 return mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 330 } 331 332 static uint32_t zynqmp_get_ps_ver(void) 333 { 334 uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 335 336 ver &= ZYNQMP_PS_VER_MASK; 337 ver >>= ZYNQMP_PS_VER_SHIFT; 338 339 return ver + 1U; 340 } 341 342 static void zynqmp_print_platform_name(void) 343 { 344 uint32_t ver = zynqmp_get_silicon_ver(); 345 uint32_t rtl = zynqmp_get_rtl_ver(); 346 char *label = "Unknown"; 347 348 switch (ver) { 349 case ZYNQMP_CSU_VERSION_QEMU: 350 label = "QEMU"; 351 break; 352 case ZYNQMP_CSU_VERSION_SILICON: 353 label = "silicon"; 354 break; 355 default: 356 /* Do nothing in default case */ 357 break; 358 } 359 360 VERBOSE("TF-A running on %s/%s at 0x%x\n", 361 zynqmp_print_silicon_idcode(), label, BL31_BASE); 362 VERBOSE("TF-A running on v%d/RTL%d.%d\n", 363 zynqmp_get_ps_ver(), (rtl & 0xf0) >> 4, rtl & 0xf); 364 } 365 #else 366 static inline void zynqmp_print_platform_name(void) { } 367 #endif 368 369 uint32_t zynqmp_get_bootmode(void) 370 { 371 uint32_t r; 372 unsigned int ret; 373 374 ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r); 375 376 if (ret != PM_RET_SUCCESS) { 377 r = mmio_read_32(CRL_APB_BOOT_MODE_USER); 378 } 379 380 return r & CRL_APB_BOOT_MODE_MASK; 381 } 382 383 void zynqmp_config_setup(void) 384 { 385 uint64_t counter_freq; 386 387 /* Configure IPI data for ZynqMP */ 388 zynqmp_ipi_config_table_init(); 389 390 zynqmp_print_platform_name(); 391 392 /* Configure counter frequency */ 393 counter_freq = read_cntfrq_el0(); 394 if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) { 395 write_cntfrq_el0(plat_get_syscnt_freq2()); 396 } 397 398 generic_delay_timer_init(); 399 } 400 401 uint32_t plat_get_syscnt_freq2(void) 402 { 403 uint32_t ver = zynqmp_get_silicon_ver(); 404 405 if (ver == ZYNQMP_CSU_VERSION_QEMU) { 406 return 65000000; 407 } else { 408 return mmio_read_32(IOU_SCNTRS_BASEFREQ); 409 } 410 } 411