1c8284409SSoren Brinkmann /* 2c8284409SSoren Brinkmann * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. 3c8284409SSoren Brinkmann * 4c8284409SSoren Brinkmann * Redistribution and use in source and binary forms, with or without 5c8284409SSoren Brinkmann * modification, are permitted provided that the following conditions are met: 6c8284409SSoren Brinkmann * 7c8284409SSoren Brinkmann * Redistributions of source code must retain the above copyright notice, this 8c8284409SSoren Brinkmann * list of conditions and the following disclaimer. 9c8284409SSoren Brinkmann * 10c8284409SSoren Brinkmann * Redistributions in binary form must reproduce the above copyright notice, 11c8284409SSoren Brinkmann * this list of conditions and the following disclaimer in the documentation 12c8284409SSoren Brinkmann * and/or other materials provided with the distribution. 13c8284409SSoren Brinkmann * 14c8284409SSoren Brinkmann * Neither the name of ARM nor the names of its contributors may be used 15c8284409SSoren Brinkmann * to endorse or promote products derived from this software without specific 16c8284409SSoren Brinkmann * prior written permission. 17c8284409SSoren Brinkmann * 18c8284409SSoren Brinkmann * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19c8284409SSoren Brinkmann * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20c8284409SSoren Brinkmann * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21c8284409SSoren Brinkmann * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22c8284409SSoren Brinkmann * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23c8284409SSoren Brinkmann * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24c8284409SSoren Brinkmann * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25c8284409SSoren Brinkmann * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26c8284409SSoren Brinkmann * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27c8284409SSoren Brinkmann * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28c8284409SSoren Brinkmann * POSSIBILITY OF SUCH DAMAGE. 29c8284409SSoren Brinkmann */ 30c8284409SSoren Brinkmann 31c8284409SSoren Brinkmann #include <debug.h> 32e1cb4da4SSoren Brinkmann #include <generic_delay_timer.h> 33c8284409SSoren Brinkmann #include <mmio.h> 34c8284409SSoren Brinkmann #include <platform.h> 35c8284409SSoren Brinkmann #include <xlat_tables.h> 36c8284409SSoren Brinkmann #include "../zynqmp_private.h" 37c8284409SSoren Brinkmann 38c8284409SSoren Brinkmann /* 39c8284409SSoren Brinkmann * Table of regions to map using the MMU. 40c8284409SSoren Brinkmann * This doesn't include TZRAM as the 'mem_layout' argument passed to 41c8284409SSoren Brinkmann * configure_mmu_elx() will give the available subset of that, 42c8284409SSoren Brinkmann */ 43c8284409SSoren Brinkmann const mmap_region_t plat_arm_mmap[] = { 44c8284409SSoren Brinkmann { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 45c8284409SSoren Brinkmann { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 46c8284409SSoren Brinkmann { CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 47c8284409SSoren Brinkmann {0} 48c8284409SSoren Brinkmann }; 49c8284409SSoren Brinkmann 50c8284409SSoren Brinkmann static unsigned int zynqmp_get_silicon_ver(void) 51c8284409SSoren Brinkmann { 52*466675c2SSoren Brinkmann static unsigned int ver; 53c8284409SSoren Brinkmann 54*466675c2SSoren Brinkmann if (!ver) { 55*466675c2SSoren Brinkmann ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + 56*466675c2SSoren Brinkmann ZYNQMP_CSU_VERSION_OFFSET); 57c8284409SSoren Brinkmann ver &= ZYNQMP_SILICON_VER_MASK; 58c8284409SSoren Brinkmann ver >>= ZYNQMP_SILICON_VER_SHIFT; 59*466675c2SSoren Brinkmann } 60c8284409SSoren Brinkmann 61c8284409SSoren Brinkmann return ver; 62c8284409SSoren Brinkmann } 63c8284409SSoren Brinkmann 64c8284409SSoren Brinkmann unsigned int zynqmp_get_uart_clk(void) 65c8284409SSoren Brinkmann { 66c8284409SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 67c8284409SSoren Brinkmann 68c8284409SSoren Brinkmann switch (ver) { 69c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_VELOCE: 70c8284409SSoren Brinkmann return 48000; 71c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_EP108: 72c8284409SSoren Brinkmann return 25000000; 73c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_QEMU: 74c8284409SSoren Brinkmann return 133000000; 75c8284409SSoren Brinkmann } 76c8284409SSoren Brinkmann 77c8284409SSoren Brinkmann return 100000000; 78c8284409SSoren Brinkmann } 79c8284409SSoren Brinkmann 80c8284409SSoren Brinkmann static unsigned int zynqmp_get_system_timer_freq(void) 81c8284409SSoren Brinkmann { 82c8284409SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 83c8284409SSoren Brinkmann 84c8284409SSoren Brinkmann switch (ver) { 85c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_VELOCE: 86c8284409SSoren Brinkmann return 10000; 87c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_EP108: 88c8284409SSoren Brinkmann return 4000000; 89c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_QEMU: 90c8284409SSoren Brinkmann return 50000000; 91c8284409SSoren Brinkmann } 92c8284409SSoren Brinkmann 93c8284409SSoren Brinkmann return 100000000; 94c8284409SSoren Brinkmann } 95c8284409SSoren Brinkmann 963104f2e7SSiva Durga Prasad Paladugu unsigned int zynqmp_get_silicon_id(void) 973104f2e7SSiva Durga Prasad Paladugu { 983104f2e7SSiva Durga Prasad Paladugu uint32_t id; 993104f2e7SSiva Durga Prasad Paladugu 1003104f2e7SSiva Durga Prasad Paladugu id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 1013104f2e7SSiva Durga Prasad Paladugu 1023104f2e7SSiva Durga Prasad Paladugu id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK; 1033104f2e7SSiva Durga Prasad Paladugu id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 1043104f2e7SSiva Durga Prasad Paladugu 1053104f2e7SSiva Durga Prasad Paladugu return id; 1063104f2e7SSiva Durga Prasad Paladugu } 1073104f2e7SSiva Durga Prasad Paladugu 108c8284409SSoren Brinkmann #if LOG_LEVEL >= LOG_LEVEL_NOTICE 109c8284409SSoren Brinkmann static const struct { 110c8284409SSoren Brinkmann unsigned int id; 111c8284409SSoren Brinkmann char *name; 112c8284409SSoren Brinkmann } zynqmp_devices[] = { 113c8284409SSoren Brinkmann { 114c8284409SSoren Brinkmann .id = 0x10, 115c8284409SSoren Brinkmann .name = "3EG", 116c8284409SSoren Brinkmann }, 117c8284409SSoren Brinkmann { 118c8284409SSoren Brinkmann .id = 0x11, 119c8284409SSoren Brinkmann .name = "2EG", 120c8284409SSoren Brinkmann }, 121c8284409SSoren Brinkmann { 122c8284409SSoren Brinkmann .id = 0x20, 123c8284409SSoren Brinkmann .name = "5EV", 124c8284409SSoren Brinkmann }, 125c8284409SSoren Brinkmann { 126c8284409SSoren Brinkmann .id = 0x21, 127c8284409SSoren Brinkmann .name = "4EV", 128c8284409SSoren Brinkmann }, 129c8284409SSoren Brinkmann { 130c8284409SSoren Brinkmann .id = 0x30, 131c8284409SSoren Brinkmann .name = "7EV", 132c8284409SSoren Brinkmann }, 133c8284409SSoren Brinkmann { 134c8284409SSoren Brinkmann .id = 0x38, 135c8284409SSoren Brinkmann .name = "9EG", 136c8284409SSoren Brinkmann }, 137c8284409SSoren Brinkmann { 138c8284409SSoren Brinkmann .id = 0x39, 139c8284409SSoren Brinkmann .name = "6EG", 140c8284409SSoren Brinkmann }, 141c8284409SSoren Brinkmann { 142c8284409SSoren Brinkmann .id = 0x40, 143c8284409SSoren Brinkmann .name = "11EG", 144c8284409SSoren Brinkmann }, 145c8284409SSoren Brinkmann { 146c8284409SSoren Brinkmann .id = 0x50, 147c8284409SSoren Brinkmann .name = "15EG", 148c8284409SSoren Brinkmann }, 149c8284409SSoren Brinkmann { 150c8284409SSoren Brinkmann .id = 0x58, 151c8284409SSoren Brinkmann .name = "19EG", 152c8284409SSoren Brinkmann }, 153c8284409SSoren Brinkmann { 154c8284409SSoren Brinkmann .id = 0x59, 155c8284409SSoren Brinkmann .name = "17EG", 156c8284409SSoren Brinkmann }, 157c8284409SSoren Brinkmann }; 158c8284409SSoren Brinkmann 159c8284409SSoren Brinkmann static char *zynqmp_get_silicon_idcode_name(void) 160c8284409SSoren Brinkmann { 161c8284409SSoren Brinkmann unsigned int id; 162c8284409SSoren Brinkmann 163c8284409SSoren Brinkmann id = zynqmp_get_silicon_id(); 164c8284409SSoren Brinkmann for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 165c8284409SSoren Brinkmann if (zynqmp_devices[i].id == id) 166c8284409SSoren Brinkmann return zynqmp_devices[i].name; 167c8284409SSoren Brinkmann } 168c8284409SSoren Brinkmann return "UNKN"; 169c8284409SSoren Brinkmann } 170c8284409SSoren Brinkmann 171c8284409SSoren Brinkmann static unsigned int zynqmp_get_rtl_ver(void) 172c8284409SSoren Brinkmann { 173c8284409SSoren Brinkmann uint32_t ver; 174c8284409SSoren Brinkmann 175c8284409SSoren Brinkmann ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 176c8284409SSoren Brinkmann ver &= ZYNQMP_RTL_VER_MASK; 177c8284409SSoren Brinkmann ver >>= ZYNQMP_RTL_VER_SHIFT; 178c8284409SSoren Brinkmann 179c8284409SSoren Brinkmann return ver; 180c8284409SSoren Brinkmann } 181c8284409SSoren Brinkmann 182c8284409SSoren Brinkmann static char *zynqmp_print_silicon_idcode(void) 183c8284409SSoren Brinkmann { 184c8284409SSoren Brinkmann uint32_t id, maskid, tmp; 185c8284409SSoren Brinkmann 186c8284409SSoren Brinkmann id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 187c8284409SSoren Brinkmann 188c8284409SSoren Brinkmann tmp = id; 189c8284409SSoren Brinkmann tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | 190648fe99eSSoren Brinkmann ZYNQMP_CSU_IDCODE_FAMILY_MASK; 191c8284409SSoren Brinkmann maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | 192648fe99eSSoren Brinkmann ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT; 193c8284409SSoren Brinkmann if (tmp != maskid) { 194c8284409SSoren Brinkmann ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid); 195c8284409SSoren Brinkmann return "UNKN"; 196c8284409SSoren Brinkmann } 197c8284409SSoren Brinkmann VERBOSE("Xilinx IDCODE 0x%x\n", id); 198c8284409SSoren Brinkmann return zynqmp_get_silicon_idcode_name(); 199c8284409SSoren Brinkmann } 200c8284409SSoren Brinkmann 201c8284409SSoren Brinkmann static unsigned int zynqmp_get_ps_ver(void) 202c8284409SSoren Brinkmann { 203c8284409SSoren Brinkmann uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 204c8284409SSoren Brinkmann 205c8284409SSoren Brinkmann ver &= ZYNQMP_PS_VER_MASK; 206c8284409SSoren Brinkmann ver >>= ZYNQMP_PS_VER_SHIFT; 207c8284409SSoren Brinkmann 208c8284409SSoren Brinkmann return ver + 1; 209c8284409SSoren Brinkmann } 210c8284409SSoren Brinkmann 211c8284409SSoren Brinkmann static void zynqmp_print_platform_name(void) 212c8284409SSoren Brinkmann { 213c8284409SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 214c8284409SSoren Brinkmann unsigned int rtl = zynqmp_get_rtl_ver(); 215c8284409SSoren Brinkmann char *label = "Unknown"; 216c8284409SSoren Brinkmann 217c8284409SSoren Brinkmann switch (ver) { 218c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_VELOCE: 219c8284409SSoren Brinkmann label = "VELOCE"; 220c8284409SSoren Brinkmann break; 221c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_EP108: 222c8284409SSoren Brinkmann label = "EP108"; 223c8284409SSoren Brinkmann break; 224c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_QEMU: 225c8284409SSoren Brinkmann label = "QEMU"; 226c8284409SSoren Brinkmann break; 227c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_SILICON: 228c8284409SSoren Brinkmann label = "silicon"; 229c8284409SSoren Brinkmann break; 230c8284409SSoren Brinkmann } 231c8284409SSoren Brinkmann 232c8284409SSoren Brinkmann NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n", 233c8284409SSoren Brinkmann zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(), 234c8284409SSoren Brinkmann (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE, 235c8284409SSoren Brinkmann zynqmp_is_pmu_up() ? ", with PMU firmware" : ""); 236c8284409SSoren Brinkmann } 237c8284409SSoren Brinkmann #else 238c8284409SSoren Brinkmann static inline void zynqmp_print_platform_name(void) { } 239c8284409SSoren Brinkmann #endif 240c8284409SSoren Brinkmann 241c8284409SSoren Brinkmann /* 242c8284409SSoren Brinkmann * Indicator for PMUFW discovery: 243c8284409SSoren Brinkmann * 0 = No FW found 244c8284409SSoren Brinkmann * non-zero = FW is present 245c8284409SSoren Brinkmann */ 246c8284409SSoren Brinkmann static int zynqmp_pmufw_present; 247c8284409SSoren Brinkmann 248c8284409SSoren Brinkmann /* 249c8284409SSoren Brinkmann * zynqmp_discover_pmufw - Discover presence of PMUFW 250c8284409SSoren Brinkmann * 251c8284409SSoren Brinkmann * Discover the presence of PMUFW and store it for later run-time queries 252c8284409SSoren Brinkmann * through zynqmp_is_pmu_up. 253c8284409SSoren Brinkmann * NOTE: This discovery method is fragile and will break if: 254c8284409SSoren Brinkmann * - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW 255c8284409SSoren Brinkmann * (be it by error or intentionally) 256c8284409SSoren Brinkmann * - XPPU/XMPU may restrict ATF's access to the PMU address space 257c8284409SSoren Brinkmann */ 258c8284409SSoren Brinkmann static int zynqmp_discover_pmufw(void) 259c8284409SSoren Brinkmann { 260c8284409SSoren Brinkmann zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL); 261c8284409SSoren Brinkmann zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT; 262c8284409SSoren Brinkmann 263c8284409SSoren Brinkmann return !!zynqmp_pmufw_present; 264c8284409SSoren Brinkmann } 265c8284409SSoren Brinkmann 266c8284409SSoren Brinkmann /* 267c8284409SSoren Brinkmann * zynqmp_is_pmu_up - Find if PMU firmware is up and running 268c8284409SSoren Brinkmann * 269c8284409SSoren Brinkmann * Return 0 if firmware is not available, non 0 otherwise 270c8284409SSoren Brinkmann */ 271c8284409SSoren Brinkmann int zynqmp_is_pmu_up(void) 272c8284409SSoren Brinkmann { 273c8284409SSoren Brinkmann return zynqmp_pmufw_present; 274c8284409SSoren Brinkmann } 275c8284409SSoren Brinkmann 2762cb5bac9SSoren Brinkmann unsigned int zynqmp_get_bootmode(void) 2772cb5bac9SSoren Brinkmann { 2782cb5bac9SSoren Brinkmann uint32_t r = mmio_read_32(CRL_APB_BOOT_MODE_USER); 2792cb5bac9SSoren Brinkmann 2802cb5bac9SSoren Brinkmann return r & CRL_APB_BOOT_MODE_MASK; 2812cb5bac9SSoren Brinkmann } 2822cb5bac9SSoren Brinkmann 283c8284409SSoren Brinkmann void zynqmp_config_setup(void) 284c8284409SSoren Brinkmann { 285c8284409SSoren Brinkmann zynqmp_discover_pmufw(); 286c8284409SSoren Brinkmann zynqmp_print_platform_name(); 287c8284409SSoren Brinkmann 288c8284409SSoren Brinkmann /* Global timer init - Program time stamp reference clk */ 289c8284409SSoren Brinkmann uint32_t val = mmio_read_32(CRL_APB_TIMESTAMP_REF_CTRL); 290c8284409SSoren Brinkmann val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT; 291c8284409SSoren Brinkmann mmio_write_32(CRL_APB_TIMESTAMP_REF_CTRL, val); 292c8284409SSoren Brinkmann 293c8284409SSoren Brinkmann /* Program freq register in System counter and enable system counter. */ 294c8284409SSoren Brinkmann mmio_write_32(IOU_SCNTRS_BASEFREQ, zynqmp_get_system_timer_freq()); 295c8284409SSoren Brinkmann mmio_write_32(IOU_SCNTRS_CONTROL, IOU_SCNTRS_CONTROL_EN); 296e1cb4da4SSoren Brinkmann 297e1cb4da4SSoren Brinkmann generic_delay_timer_init(); 298c8284409SSoren Brinkmann } 299c8284409SSoren Brinkmann 300f3d3b316SAntonio Nino Diaz unsigned int plat_get_syscnt_freq2(void) 301c8284409SSoren Brinkmann { 302f3d3b316SAntonio Nino Diaz unsigned int counter_base_frequency; 303c8284409SSoren Brinkmann 304c8284409SSoren Brinkmann /* FIXME: Read the frequency from Frequency modes table */ 305c8284409SSoren Brinkmann counter_base_frequency = zynqmp_get_system_timer_freq(); 306c8284409SSoren Brinkmann 307c8284409SSoren Brinkmann return counter_base_frequency; 308c8284409SSoren Brinkmann } 309