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