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 <debug.h> 8 #include <generic_delay_timer.h> 9 #include <mmio.h> 10 #include <platform.h> 11 #include <xlat_tables.h> 12 #include "../zynqmp_private.h" 13 #include "pm_api_sys.h" 14 15 /* 16 * Table of regions to map using the MMU. 17 * This doesn't include TZRAM as the 'mem_layout' argument passed to 18 * configure_mmu_elx() will give the available subset of that, 19 */ 20 const mmap_region_t plat_arm_mmap[] = { 21 { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 22 { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 23 { CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 24 {0} 25 }; 26 27 static unsigned int zynqmp_get_silicon_ver(void) 28 { 29 static unsigned int ver; 30 31 if (!ver) { 32 ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + 33 ZYNQMP_CSU_VERSION_OFFSET); 34 ver &= ZYNQMP_SILICON_VER_MASK; 35 ver >>= ZYNQMP_SILICON_VER_SHIFT; 36 } 37 38 return ver; 39 } 40 41 unsigned int zynqmp_get_uart_clk(void) 42 { 43 unsigned int ver = zynqmp_get_silicon_ver(); 44 45 switch (ver) { 46 case ZYNQMP_CSU_VERSION_VELOCE: 47 return 48000; 48 case ZYNQMP_CSU_VERSION_EP108: 49 return 25000000; 50 case ZYNQMP_CSU_VERSION_QEMU: 51 return 133000000; 52 default: 53 /* Do nothing in default case */ 54 break; 55 } 56 57 return 100000000; 58 } 59 60 #if LOG_LEVEL >= LOG_LEVEL_NOTICE 61 static const struct { 62 unsigned int id; 63 char *name; 64 } zynqmp_devices[] = { 65 { 66 .id = 0x10, 67 .name = "3EG", 68 }, 69 { 70 .id = 0x11, 71 .name = "2EG", 72 }, 73 { 74 .id = 0x20, 75 .name = "5EV", 76 }, 77 { 78 .id = 0x21, 79 .name = "4EV", 80 }, 81 { 82 .id = 0x30, 83 .name = "7EV", 84 }, 85 { 86 .id = 0x38, 87 .name = "9EG", 88 }, 89 { 90 .id = 0x39, 91 .name = "6EG", 92 }, 93 { 94 .id = 0x40, 95 .name = "11EG", 96 }, 97 { 98 .id = 0x50, 99 .name = "15EG", 100 }, 101 { 102 .id = 0x58, 103 .name = "19EG", 104 }, 105 { 106 .id = 0x59, 107 .name = "17EG", 108 }, 109 }; 110 111 static unsigned int zynqmp_get_silicon_id(void) 112 { 113 uint32_t id; 114 115 id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 116 117 id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK; 118 id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 119 120 return id; 121 } 122 123 static char *zynqmp_get_silicon_idcode_name(void) 124 { 125 unsigned int id; 126 127 id = zynqmp_get_silicon_id(); 128 for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 129 if (zynqmp_devices[i].id == id) 130 return zynqmp_devices[i].name; 131 } 132 return "UNKN"; 133 } 134 135 static unsigned int zynqmp_get_rtl_ver(void) 136 { 137 uint32_t ver; 138 139 ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 140 ver &= ZYNQMP_RTL_VER_MASK; 141 ver >>= ZYNQMP_RTL_VER_SHIFT; 142 143 return ver; 144 } 145 146 static char *zynqmp_print_silicon_idcode(void) 147 { 148 uint32_t id, maskid, tmp; 149 150 id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 151 152 tmp = id; 153 tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | 154 ZYNQMP_CSU_IDCODE_FAMILY_MASK; 155 maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | 156 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT; 157 if (tmp != maskid) { 158 ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid); 159 return "UNKN"; 160 } 161 VERBOSE("Xilinx IDCODE 0x%x\n", id); 162 return zynqmp_get_silicon_idcode_name(); 163 } 164 165 static unsigned int zynqmp_get_ps_ver(void) 166 { 167 uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 168 169 ver &= ZYNQMP_PS_VER_MASK; 170 ver >>= ZYNQMP_PS_VER_SHIFT; 171 172 return ver + 1; 173 } 174 175 static void zynqmp_print_platform_name(void) 176 { 177 unsigned int ver = zynqmp_get_silicon_ver(); 178 unsigned int rtl = zynqmp_get_rtl_ver(); 179 char *label = "Unknown"; 180 181 switch (ver) { 182 case ZYNQMP_CSU_VERSION_VELOCE: 183 label = "VELOCE"; 184 break; 185 case ZYNQMP_CSU_VERSION_EP108: 186 label = "EP108"; 187 break; 188 case ZYNQMP_CSU_VERSION_QEMU: 189 label = "QEMU"; 190 break; 191 case ZYNQMP_CSU_VERSION_SILICON: 192 label = "silicon"; 193 break; 194 default: 195 /* Do nothing in default case */ 196 break; 197 } 198 199 NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n", 200 zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(), 201 (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE, 202 zynqmp_is_pmu_up() ? ", with PMU firmware" : ""); 203 } 204 #else 205 static inline void zynqmp_print_platform_name(void) { } 206 #endif 207 208 /* 209 * Indicator for PMUFW discovery: 210 * 0 = No FW found 211 * non-zero = FW is present 212 */ 213 static int zynqmp_pmufw_present; 214 215 /* 216 * zynqmp_discover_pmufw - Discover presence of PMUFW 217 * 218 * Discover the presence of PMUFW and store it for later run-time queries 219 * through zynqmp_is_pmu_up. 220 * NOTE: This discovery method is fragile and will break if: 221 * - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW 222 * (be it by error or intentionally) 223 * - XPPU/XMPU may restrict ATF's access to the PMU address space 224 */ 225 static int zynqmp_discover_pmufw(void) 226 { 227 zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL); 228 zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT; 229 230 return !!zynqmp_pmufw_present; 231 } 232 233 /* 234 * zynqmp_is_pmu_up - Find if PMU firmware is up and running 235 * 236 * Return 0 if firmware is not available, non 0 otherwise 237 */ 238 int zynqmp_is_pmu_up(void) 239 { 240 return zynqmp_pmufw_present; 241 } 242 243 unsigned int zynqmp_get_bootmode(void) 244 { 245 uint32_t r; 246 247 if (zynqmp_is_pmu_up()) 248 pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r); 249 else 250 r = mmio_read_32(CRL_APB_BOOT_MODE_USER); 251 252 return r & CRL_APB_BOOT_MODE_MASK; 253 } 254 255 void zynqmp_config_setup(void) 256 { 257 zynqmp_discover_pmufw(); 258 zynqmp_print_platform_name(); 259 generic_delay_timer_init(); 260 } 261 262 unsigned int plat_get_syscnt_freq2(void) 263 { 264 unsigned int ver = zynqmp_get_silicon_ver(); 265 266 switch (ver) { 267 case ZYNQMP_CSU_VERSION_VELOCE: 268 return 10000; 269 case ZYNQMP_CSU_VERSION_EP108: 270 return 4000000; 271 case ZYNQMP_CSU_VERSION_QEMU: 272 return 50000000; 273 default: 274 /* Do nothing in default case */ 275 break; 276 } 277 278 return mmio_read_32(IOU_SCNTRS_BASEFREQ); 279 } 280