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