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