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