1c8284409SSoren Brinkmann /* 2c8284409SSoren Brinkmann * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. 3c8284409SSoren Brinkmann * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5c8284409SSoren Brinkmann */ 6c8284409SSoren Brinkmann 7c8284409SSoren Brinkmann #include <debug.h> 8e1cb4da4SSoren Brinkmann #include <generic_delay_timer.h> 9c8284409SSoren Brinkmann #include <mmio.h> 10c8284409SSoren Brinkmann #include <platform.h> 11c8284409SSoren Brinkmann #include <xlat_tables.h> 12c8284409SSoren Brinkmann #include "../zynqmp_private.h" 1329bd0e66SSiva Durga Prasad Paladugu #include "pm_api_sys.h" 14c8284409SSoren Brinkmann 15c8284409SSoren Brinkmann /* 16c8284409SSoren Brinkmann * Table of regions to map using the MMU. 17c8284409SSoren Brinkmann * This doesn't include TZRAM as the 'mem_layout' argument passed to 18c8284409SSoren Brinkmann * configure_mmu_elx() will give the available subset of that, 19c8284409SSoren Brinkmann */ 20c8284409SSoren Brinkmann const mmap_region_t plat_arm_mmap[] = { 21c8284409SSoren Brinkmann { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 22c8284409SSoren Brinkmann { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 23c8284409SSoren Brinkmann { CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 24c8284409SSoren Brinkmann {0} 25c8284409SSoren Brinkmann }; 26c8284409SSoren Brinkmann 27c8284409SSoren Brinkmann static unsigned int zynqmp_get_silicon_ver(void) 28c8284409SSoren Brinkmann { 29466675c2SSoren Brinkmann static unsigned int ver; 30c8284409SSoren Brinkmann 31466675c2SSoren Brinkmann if (!ver) { 32466675c2SSoren Brinkmann ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + 33466675c2SSoren Brinkmann ZYNQMP_CSU_VERSION_OFFSET); 34c8284409SSoren Brinkmann ver &= ZYNQMP_SILICON_VER_MASK; 35c8284409SSoren Brinkmann ver >>= ZYNQMP_SILICON_VER_SHIFT; 36466675c2SSoren Brinkmann } 37c8284409SSoren Brinkmann 38c8284409SSoren Brinkmann return ver; 39c8284409SSoren Brinkmann } 40c8284409SSoren Brinkmann 41c8284409SSoren Brinkmann unsigned int zynqmp_get_uart_clk(void) 42c8284409SSoren Brinkmann { 43c8284409SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 44c8284409SSoren Brinkmann 45c8284409SSoren Brinkmann switch (ver) { 46c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_VELOCE: 47c8284409SSoren Brinkmann return 48000; 48c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_EP108: 49c8284409SSoren Brinkmann return 25000000; 50c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_QEMU: 51c8284409SSoren Brinkmann return 133000000; 52649c48f5SJonathan Wright default: 53649c48f5SJonathan Wright /* Do nothing in default case */ 54649c48f5SJonathan Wright break; 55c8284409SSoren Brinkmann } 56c8284409SSoren Brinkmann 57c8284409SSoren Brinkmann return 100000000; 58c8284409SSoren Brinkmann } 59c8284409SSoren Brinkmann 60c8284409SSoren Brinkmann #if LOG_LEVEL >= LOG_LEVEL_NOTICE 61c8284409SSoren Brinkmann static const struct { 62c8284409SSoren Brinkmann unsigned int id; 63c8284409SSoren Brinkmann char *name; 64c8284409SSoren Brinkmann } zynqmp_devices[] = { 65c8284409SSoren Brinkmann { 66c8284409SSoren Brinkmann .id = 0x10, 67c8284409SSoren Brinkmann .name = "3EG", 68c8284409SSoren Brinkmann }, 69c8284409SSoren Brinkmann { 70c8284409SSoren Brinkmann .id = 0x11, 71c8284409SSoren Brinkmann .name = "2EG", 72c8284409SSoren Brinkmann }, 73c8284409SSoren Brinkmann { 74c8284409SSoren Brinkmann .id = 0x20, 75c8284409SSoren Brinkmann .name = "5EV", 76c8284409SSoren Brinkmann }, 77c8284409SSoren Brinkmann { 78c8284409SSoren Brinkmann .id = 0x21, 79c8284409SSoren Brinkmann .name = "4EV", 80c8284409SSoren Brinkmann }, 81c8284409SSoren Brinkmann { 82c8284409SSoren Brinkmann .id = 0x30, 83c8284409SSoren Brinkmann .name = "7EV", 84c8284409SSoren Brinkmann }, 85c8284409SSoren Brinkmann { 86c8284409SSoren Brinkmann .id = 0x38, 87c8284409SSoren Brinkmann .name = "9EG", 88c8284409SSoren Brinkmann }, 89c8284409SSoren Brinkmann { 90c8284409SSoren Brinkmann .id = 0x39, 91c8284409SSoren Brinkmann .name = "6EG", 92c8284409SSoren Brinkmann }, 93c8284409SSoren Brinkmann { 94c8284409SSoren Brinkmann .id = 0x40, 95c8284409SSoren Brinkmann .name = "11EG", 96c8284409SSoren Brinkmann }, 97c8284409SSoren Brinkmann { 98c8284409SSoren Brinkmann .id = 0x50, 99c8284409SSoren Brinkmann .name = "15EG", 100c8284409SSoren Brinkmann }, 101c8284409SSoren Brinkmann { 102c8284409SSoren Brinkmann .id = 0x58, 103c8284409SSoren Brinkmann .name = "19EG", 104c8284409SSoren Brinkmann }, 105c8284409SSoren Brinkmann { 106c8284409SSoren Brinkmann .id = 0x59, 107c8284409SSoren Brinkmann .name = "17EG", 108c8284409SSoren Brinkmann }, 109*d9710aebSSiva Durga Prasad Paladugu { 110*d9710aebSSiva Durga Prasad Paladugu .id = 0x60, 111*d9710aebSSiva Durga Prasad Paladugu .name = "28DR", 112*d9710aebSSiva Durga Prasad Paladugu }, 113*d9710aebSSiva Durga Prasad Paladugu { 114*d9710aebSSiva Durga Prasad Paladugu .id = 0x61, 115*d9710aebSSiva Durga Prasad Paladugu .name = "21DR", 116*d9710aebSSiva Durga Prasad Paladugu }, 117*d9710aebSSiva Durga Prasad Paladugu { 118*d9710aebSSiva Durga Prasad Paladugu .id = 0x62, 119*d9710aebSSiva Durga Prasad Paladugu .name = "29DR", 120*d9710aebSSiva Durga Prasad Paladugu }, 121*d9710aebSSiva Durga Prasad Paladugu { 122*d9710aebSSiva Durga Prasad Paladugu .id = 0x63, 123*d9710aebSSiva Durga Prasad Paladugu .name = "23DR", 124*d9710aebSSiva Durga Prasad Paladugu }, 125*d9710aebSSiva Durga Prasad Paladugu { 126*d9710aebSSiva Durga Prasad Paladugu .id = 0x64, 127*d9710aebSSiva Durga Prasad Paladugu .name = "27DR", 128*d9710aebSSiva Durga Prasad Paladugu }, 129*d9710aebSSiva Durga Prasad Paladugu { 130*d9710aebSSiva Durga Prasad Paladugu .id = 0x65, 131*d9710aebSSiva Durga Prasad Paladugu .name = "25DR", 132*d9710aebSSiva Durga Prasad Paladugu }, 133c8284409SSoren Brinkmann }; 134c8284409SSoren Brinkmann 13546cb684fSSoren Brinkmann static unsigned int zynqmp_get_silicon_id(void) 13646cb684fSSoren Brinkmann { 13746cb684fSSoren Brinkmann uint32_t id; 13846cb684fSSoren Brinkmann 13946cb684fSSoren Brinkmann id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 14046cb684fSSoren Brinkmann 14146cb684fSSoren Brinkmann id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK; 14246cb684fSSoren Brinkmann id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 14346cb684fSSoren Brinkmann 14446cb684fSSoren Brinkmann return id; 14546cb684fSSoren Brinkmann } 14646cb684fSSoren Brinkmann 147c8284409SSoren Brinkmann static char *zynqmp_get_silicon_idcode_name(void) 148c8284409SSoren Brinkmann { 149c8284409SSoren Brinkmann unsigned int id; 150c8284409SSoren Brinkmann 151c8284409SSoren Brinkmann id = zynqmp_get_silicon_id(); 152c8284409SSoren Brinkmann for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 153c8284409SSoren Brinkmann if (zynqmp_devices[i].id == id) 154c8284409SSoren Brinkmann return zynqmp_devices[i].name; 155c8284409SSoren Brinkmann } 156c8284409SSoren Brinkmann return "UNKN"; 157c8284409SSoren Brinkmann } 158c8284409SSoren Brinkmann 159c8284409SSoren Brinkmann static unsigned int zynqmp_get_rtl_ver(void) 160c8284409SSoren Brinkmann { 161c8284409SSoren Brinkmann uint32_t ver; 162c8284409SSoren Brinkmann 163c8284409SSoren Brinkmann ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 164c8284409SSoren Brinkmann ver &= ZYNQMP_RTL_VER_MASK; 165c8284409SSoren Brinkmann ver >>= ZYNQMP_RTL_VER_SHIFT; 166c8284409SSoren Brinkmann 167c8284409SSoren Brinkmann return ver; 168c8284409SSoren Brinkmann } 169c8284409SSoren Brinkmann 170c8284409SSoren Brinkmann static char *zynqmp_print_silicon_idcode(void) 171c8284409SSoren Brinkmann { 172c8284409SSoren Brinkmann uint32_t id, maskid, tmp; 173c8284409SSoren Brinkmann 174c8284409SSoren Brinkmann id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 175c8284409SSoren Brinkmann 176c8284409SSoren Brinkmann tmp = id; 177c8284409SSoren Brinkmann tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | 178648fe99eSSoren Brinkmann ZYNQMP_CSU_IDCODE_FAMILY_MASK; 179c8284409SSoren Brinkmann maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | 180648fe99eSSoren Brinkmann ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT; 181c8284409SSoren Brinkmann if (tmp != maskid) { 182c8284409SSoren Brinkmann ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid); 183c8284409SSoren Brinkmann return "UNKN"; 184c8284409SSoren Brinkmann } 185c8284409SSoren Brinkmann VERBOSE("Xilinx IDCODE 0x%x\n", id); 186c8284409SSoren Brinkmann return zynqmp_get_silicon_idcode_name(); 187c8284409SSoren Brinkmann } 188c8284409SSoren Brinkmann 189c8284409SSoren Brinkmann static unsigned int zynqmp_get_ps_ver(void) 190c8284409SSoren Brinkmann { 191c8284409SSoren Brinkmann uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 192c8284409SSoren Brinkmann 193c8284409SSoren Brinkmann ver &= ZYNQMP_PS_VER_MASK; 194c8284409SSoren Brinkmann ver >>= ZYNQMP_PS_VER_SHIFT; 195c8284409SSoren Brinkmann 196c8284409SSoren Brinkmann return ver + 1; 197c8284409SSoren Brinkmann } 198c8284409SSoren Brinkmann 199c8284409SSoren Brinkmann static void zynqmp_print_platform_name(void) 200c8284409SSoren Brinkmann { 201c8284409SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 202c8284409SSoren Brinkmann unsigned int rtl = zynqmp_get_rtl_ver(); 203c8284409SSoren Brinkmann char *label = "Unknown"; 204c8284409SSoren Brinkmann 205c8284409SSoren Brinkmann switch (ver) { 206c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_VELOCE: 207c8284409SSoren Brinkmann label = "VELOCE"; 208c8284409SSoren Brinkmann break; 209c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_EP108: 210c8284409SSoren Brinkmann label = "EP108"; 211c8284409SSoren Brinkmann break; 212c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_QEMU: 213c8284409SSoren Brinkmann label = "QEMU"; 214c8284409SSoren Brinkmann break; 215c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_SILICON: 216c8284409SSoren Brinkmann label = "silicon"; 217c8284409SSoren Brinkmann break; 218649c48f5SJonathan Wright default: 219649c48f5SJonathan Wright /* Do nothing in default case */ 220649c48f5SJonathan Wright break; 221c8284409SSoren Brinkmann } 222c8284409SSoren Brinkmann 223c8284409SSoren Brinkmann NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n", 224c8284409SSoren Brinkmann zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(), 225c8284409SSoren Brinkmann (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE, 226c8284409SSoren Brinkmann zynqmp_is_pmu_up() ? ", with PMU firmware" : ""); 227c8284409SSoren Brinkmann } 228c8284409SSoren Brinkmann #else 229c8284409SSoren Brinkmann static inline void zynqmp_print_platform_name(void) { } 230c8284409SSoren Brinkmann #endif 231c8284409SSoren Brinkmann 232c8284409SSoren Brinkmann /* 233c8284409SSoren Brinkmann * Indicator for PMUFW discovery: 234c8284409SSoren Brinkmann * 0 = No FW found 235c8284409SSoren Brinkmann * non-zero = FW is present 236c8284409SSoren Brinkmann */ 237c8284409SSoren Brinkmann static int zynqmp_pmufw_present; 238c8284409SSoren Brinkmann 239c8284409SSoren Brinkmann /* 240c8284409SSoren Brinkmann * zynqmp_discover_pmufw - Discover presence of PMUFW 241c8284409SSoren Brinkmann * 242c8284409SSoren Brinkmann * Discover the presence of PMUFW and store it for later run-time queries 243c8284409SSoren Brinkmann * through zynqmp_is_pmu_up. 244c8284409SSoren Brinkmann * NOTE: This discovery method is fragile and will break if: 245c8284409SSoren Brinkmann * - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW 246c8284409SSoren Brinkmann * (be it by error or intentionally) 247c8284409SSoren Brinkmann * - XPPU/XMPU may restrict ATF's access to the PMU address space 248c8284409SSoren Brinkmann */ 249c8284409SSoren Brinkmann static int zynqmp_discover_pmufw(void) 250c8284409SSoren Brinkmann { 251c8284409SSoren Brinkmann zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL); 252c8284409SSoren Brinkmann zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT; 253c8284409SSoren Brinkmann 254c8284409SSoren Brinkmann return !!zynqmp_pmufw_present; 255c8284409SSoren Brinkmann } 256c8284409SSoren Brinkmann 257c8284409SSoren Brinkmann /* 258c8284409SSoren Brinkmann * zynqmp_is_pmu_up - Find if PMU firmware is up and running 259c8284409SSoren Brinkmann * 260c8284409SSoren Brinkmann * Return 0 if firmware is not available, non 0 otherwise 261c8284409SSoren Brinkmann */ 262c8284409SSoren Brinkmann int zynqmp_is_pmu_up(void) 263c8284409SSoren Brinkmann { 264c8284409SSoren Brinkmann return zynqmp_pmufw_present; 265c8284409SSoren Brinkmann } 266c8284409SSoren Brinkmann 2672cb5bac9SSoren Brinkmann unsigned int zynqmp_get_bootmode(void) 2682cb5bac9SSoren Brinkmann { 26929bd0e66SSiva Durga Prasad Paladugu uint32_t r; 27029bd0e66SSiva Durga Prasad Paladugu 27129bd0e66SSiva Durga Prasad Paladugu if (zynqmp_is_pmu_up()) 27229bd0e66SSiva Durga Prasad Paladugu pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r); 27329bd0e66SSiva Durga Prasad Paladugu else 27429bd0e66SSiva Durga Prasad Paladugu r = mmio_read_32(CRL_APB_BOOT_MODE_USER); 2752cb5bac9SSoren Brinkmann 2762cb5bac9SSoren Brinkmann return r & CRL_APB_BOOT_MODE_MASK; 2772cb5bac9SSoren Brinkmann } 2782cb5bac9SSoren Brinkmann 279c8284409SSoren Brinkmann void zynqmp_config_setup(void) 280c8284409SSoren Brinkmann { 281c8284409SSoren Brinkmann zynqmp_discover_pmufw(); 282c8284409SSoren Brinkmann zynqmp_print_platform_name(); 283e1cb4da4SSoren Brinkmann generic_delay_timer_init(); 284c8284409SSoren Brinkmann } 285c8284409SSoren Brinkmann 286f3d3b316SAntonio Nino Diaz unsigned int plat_get_syscnt_freq2(void) 287c8284409SSoren Brinkmann { 288e89f4af7SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 289c8284409SSoren Brinkmann 290e89f4af7SSoren Brinkmann switch (ver) { 291e89f4af7SSoren Brinkmann case ZYNQMP_CSU_VERSION_VELOCE: 292e89f4af7SSoren Brinkmann return 10000; 293e89f4af7SSoren Brinkmann case ZYNQMP_CSU_VERSION_EP108: 294e89f4af7SSoren Brinkmann return 4000000; 295e89f4af7SSoren Brinkmann case ZYNQMP_CSU_VERSION_QEMU: 296e89f4af7SSoren Brinkmann return 50000000; 297649c48f5SJonathan Wright default: 298649c48f5SJonathan Wright /* Do nothing in default case */ 299649c48f5SJonathan Wright break; 300e89f4af7SSoren Brinkmann } 301c8284409SSoren Brinkmann 302e89f4af7SSoren Brinkmann return mmio_read_32(IOU_SCNTRS_BASEFREQ); 303c8284409SSoren Brinkmann } 304