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