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