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 791bf4c5cSSiva Durga Prasad Paladugu #include <stdbool.h> 891bf4c5cSSiva Durga Prasad Paladugu #include <string.h> 909d40e0eSAntonio Nino Diaz 1009d40e0eSAntonio Nino Diaz #include <common/debug.h> 1109d40e0eSAntonio Nino Diaz #include <drivers/generic_delay_timer.h> 1209d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 1309d40e0eSAntonio Nino Diaz #include <lib/xlat_tables/xlat_tables.h> 14*31c3842eSJolly Shah #include <plat_private.h> 1509d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 1609d40e0eSAntonio Nino Diaz 1729bd0e66SSiva Durga Prasad Paladugu #include "pm_api_sys.h" 18c8284409SSoren Brinkmann 19c8284409SSoren Brinkmann /* 20c8284409SSoren Brinkmann * Table of regions to map using the MMU. 21c8284409SSoren Brinkmann * This doesn't include TZRAM as the 'mem_layout' argument passed to 22c8284409SSoren Brinkmann * configure_mmu_elx() will give the available subset of that, 23c8284409SSoren Brinkmann */ 24c8284409SSoren Brinkmann const mmap_region_t plat_arm_mmap[] = { 25c8284409SSoren Brinkmann { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 26c8284409SSoren Brinkmann { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 27c8284409SSoren Brinkmann { CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, 28c8284409SSoren Brinkmann {0} 29c8284409SSoren Brinkmann }; 30c8284409SSoren Brinkmann 31c8284409SSoren Brinkmann static unsigned int zynqmp_get_silicon_ver(void) 32c8284409SSoren Brinkmann { 33466675c2SSoren Brinkmann static unsigned int ver; 34c8284409SSoren Brinkmann 35466675c2SSoren Brinkmann if (!ver) { 36466675c2SSoren Brinkmann ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + 37466675c2SSoren Brinkmann ZYNQMP_CSU_VERSION_OFFSET); 38c8284409SSoren Brinkmann ver &= ZYNQMP_SILICON_VER_MASK; 39c8284409SSoren Brinkmann ver >>= ZYNQMP_SILICON_VER_SHIFT; 40466675c2SSoren Brinkmann } 41c8284409SSoren Brinkmann 42c8284409SSoren Brinkmann return ver; 43c8284409SSoren Brinkmann } 44c8284409SSoren Brinkmann 45c8284409SSoren Brinkmann unsigned int zynqmp_get_uart_clk(void) 46c8284409SSoren Brinkmann { 47c8284409SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 48c8284409SSoren Brinkmann 49976c2680SSiva Durga Prasad Paladugu if (ver == ZYNQMP_CSU_VERSION_QEMU) 50c8284409SSoren Brinkmann return 133000000; 51976c2680SSiva Durga Prasad Paladugu else 52c8284409SSoren Brinkmann return 100000000; 53c8284409SSoren Brinkmann } 54c8284409SSoren Brinkmann 55c8284409SSoren Brinkmann #if LOG_LEVEL >= LOG_LEVEL_NOTICE 56c8284409SSoren Brinkmann static const struct { 57c8284409SSoren Brinkmann unsigned int id; 58915d4872SSiva Durga Prasad Paladugu unsigned int ver; 59c8284409SSoren Brinkmann char *name; 6091bf4c5cSSiva Durga Prasad Paladugu bool evexists; 61c8284409SSoren Brinkmann } zynqmp_devices[] = { 62c8284409SSoren Brinkmann { 63c8284409SSoren Brinkmann .id = 0x10, 64c8284409SSoren Brinkmann .name = "3EG", 65c8284409SSoren Brinkmann }, 66c8284409SSoren Brinkmann { 67915d4872SSiva Durga Prasad Paladugu .id = 0x10, 68915d4872SSiva Durga Prasad Paladugu .ver = 0x2c, 69915d4872SSiva Durga Prasad Paladugu .name = "3CG", 70915d4872SSiva Durga Prasad Paladugu }, 71915d4872SSiva Durga Prasad Paladugu { 72c8284409SSoren Brinkmann .id = 0x11, 73c8284409SSoren Brinkmann .name = "2EG", 74c8284409SSoren Brinkmann }, 75c8284409SSoren Brinkmann { 76915d4872SSiva Durga Prasad Paladugu .id = 0x11, 77915d4872SSiva Durga Prasad Paladugu .ver = 0x2c, 78915d4872SSiva Durga Prasad Paladugu .name = "2CG", 79915d4872SSiva Durga Prasad Paladugu }, 80915d4872SSiva Durga Prasad Paladugu { 81c8284409SSoren Brinkmann .id = 0x20, 82c8284409SSoren Brinkmann .name = "5EV", 8391bf4c5cSSiva Durga Prasad Paladugu .evexists = true, 84c8284409SSoren Brinkmann }, 85c8284409SSoren Brinkmann { 86915d4872SSiva Durga Prasad Paladugu .id = 0x20, 87915d4872SSiva Durga Prasad Paladugu .ver = 0x100, 88915d4872SSiva Durga Prasad Paladugu .name = "5EG", 8991bf4c5cSSiva Durga Prasad Paladugu .evexists = true, 90915d4872SSiva Durga Prasad Paladugu }, 91915d4872SSiva Durga Prasad Paladugu { 92915d4872SSiva Durga Prasad Paladugu .id = 0x20, 93915d4872SSiva Durga Prasad Paladugu .ver = 0x12c, 94915d4872SSiva Durga Prasad Paladugu .name = "5CG", 95915d4872SSiva Durga Prasad Paladugu }, 96915d4872SSiva Durga Prasad Paladugu { 97c8284409SSoren Brinkmann .id = 0x21, 98c8284409SSoren Brinkmann .name = "4EV", 9991bf4c5cSSiva Durga Prasad Paladugu .evexists = true, 100c8284409SSoren Brinkmann }, 101c8284409SSoren Brinkmann { 102915d4872SSiva Durga Prasad Paladugu .id = 0x21, 103915d4872SSiva Durga Prasad Paladugu .ver = 0x100, 104915d4872SSiva Durga Prasad Paladugu .name = "4EG", 10591bf4c5cSSiva Durga Prasad Paladugu .evexists = true, 106915d4872SSiva Durga Prasad Paladugu }, 107915d4872SSiva Durga Prasad Paladugu { 108915d4872SSiva Durga Prasad Paladugu .id = 0x21, 109915d4872SSiva Durga Prasad Paladugu .ver = 0x12c, 110915d4872SSiva Durga Prasad Paladugu .name = "4CG", 111915d4872SSiva Durga Prasad Paladugu }, 112915d4872SSiva Durga Prasad Paladugu { 113c8284409SSoren Brinkmann .id = 0x30, 114c8284409SSoren Brinkmann .name = "7EV", 11591bf4c5cSSiva Durga Prasad Paladugu .evexists = true, 116c8284409SSoren Brinkmann }, 117c8284409SSoren Brinkmann { 118915d4872SSiva Durga Prasad Paladugu .id = 0x30, 119915d4872SSiva Durga Prasad Paladugu .ver = 0x100, 120915d4872SSiva Durga Prasad Paladugu .name = "7EG", 12191bf4c5cSSiva Durga Prasad Paladugu .evexists = true, 122915d4872SSiva Durga Prasad Paladugu }, 123915d4872SSiva Durga Prasad Paladugu { 124915d4872SSiva Durga Prasad Paladugu .id = 0x30, 125915d4872SSiva Durga Prasad Paladugu .ver = 0x12c, 126915d4872SSiva Durga Prasad Paladugu .name = "7CG", 127915d4872SSiva Durga Prasad Paladugu }, 128915d4872SSiva Durga Prasad Paladugu { 129c8284409SSoren Brinkmann .id = 0x38, 130c8284409SSoren Brinkmann .name = "9EG", 131c8284409SSoren Brinkmann }, 132c8284409SSoren Brinkmann { 133915d4872SSiva Durga Prasad Paladugu .id = 0x38, 134915d4872SSiva Durga Prasad Paladugu .ver = 0x2c, 135915d4872SSiva Durga Prasad Paladugu .name = "9CG", 136915d4872SSiva Durga Prasad Paladugu }, 137915d4872SSiva Durga Prasad Paladugu { 138c8284409SSoren Brinkmann .id = 0x39, 139c8284409SSoren Brinkmann .name = "6EG", 140c8284409SSoren Brinkmann }, 141c8284409SSoren Brinkmann { 142915d4872SSiva Durga Prasad Paladugu .id = 0x39, 143915d4872SSiva Durga Prasad Paladugu .ver = 0x2c, 144915d4872SSiva Durga Prasad Paladugu .name = "6CG", 145915d4872SSiva Durga Prasad Paladugu }, 146915d4872SSiva Durga Prasad Paladugu { 147c8284409SSoren Brinkmann .id = 0x40, 148c8284409SSoren Brinkmann .name = "11EG", 149c8284409SSoren Brinkmann }, 150915d4872SSiva Durga Prasad Paladugu { /* For testing purpose only */ 151915d4872SSiva Durga Prasad Paladugu .id = 0x50, 152915d4872SSiva Durga Prasad Paladugu .ver = 0x2c, 153915d4872SSiva Durga Prasad Paladugu .name = "15CG", 154915d4872SSiva Durga Prasad Paladugu }, 155c8284409SSoren Brinkmann { 156c8284409SSoren Brinkmann .id = 0x50, 157c8284409SSoren Brinkmann .name = "15EG", 158c8284409SSoren Brinkmann }, 159c8284409SSoren Brinkmann { 160c8284409SSoren Brinkmann .id = 0x58, 161c8284409SSoren Brinkmann .name = "19EG", 162c8284409SSoren Brinkmann }, 163c8284409SSoren Brinkmann { 164c8284409SSoren Brinkmann .id = 0x59, 165c8284409SSoren Brinkmann .name = "17EG", 166c8284409SSoren Brinkmann }, 167d9710aebSSiva Durga Prasad Paladugu { 168d9710aebSSiva Durga Prasad Paladugu .id = 0x60, 169d9710aebSSiva Durga Prasad Paladugu .name = "28DR", 170d9710aebSSiva Durga Prasad Paladugu }, 171d9710aebSSiva Durga Prasad Paladugu { 172d9710aebSSiva Durga Prasad Paladugu .id = 0x61, 173d9710aebSSiva Durga Prasad Paladugu .name = "21DR", 174d9710aebSSiva Durga Prasad Paladugu }, 175d9710aebSSiva Durga Prasad Paladugu { 176d9710aebSSiva Durga Prasad Paladugu .id = 0x62, 177d9710aebSSiva Durga Prasad Paladugu .name = "29DR", 178d9710aebSSiva Durga Prasad Paladugu }, 179d9710aebSSiva Durga Prasad Paladugu { 180d9710aebSSiva Durga Prasad Paladugu .id = 0x63, 181d9710aebSSiva Durga Prasad Paladugu .name = "23DR", 182d9710aebSSiva Durga Prasad Paladugu }, 183d9710aebSSiva Durga Prasad Paladugu { 184d9710aebSSiva Durga Prasad Paladugu .id = 0x64, 185d9710aebSSiva Durga Prasad Paladugu .name = "27DR", 186d9710aebSSiva Durga Prasad Paladugu }, 187d9710aebSSiva Durga Prasad Paladugu { 188d9710aebSSiva Durga Prasad Paladugu .id = 0x65, 189d9710aebSSiva Durga Prasad Paladugu .name = "25DR", 190d9710aebSSiva Durga Prasad Paladugu }, 191c8284409SSoren Brinkmann }; 192c8284409SSoren Brinkmann 19391bf4c5cSSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_BIT 9 19491bf4c5cSSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) 19591bf4c5cSSiva Durga Prasad Paladugu #define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) 196915d4872SSiva Durga Prasad Paladugu 197c8284409SSoren Brinkmann static char *zynqmp_get_silicon_idcode_name(void) 198c8284409SSoren Brinkmann { 19991bf4c5cSSiva Durga Prasad Paladugu uint32_t id, ver, chipid[2]; 20091bf4c5cSSiva Durga Prasad Paladugu size_t i, j, len; 20191bf4c5cSSiva Durga Prasad Paladugu const char *name = "EG/EV"; 202c8284409SSoren Brinkmann 2030435ba64SSiva Durga Prasad Paladugu #ifdef IMAGE_BL32 2040435ba64SSiva Durga Prasad Paladugu /* 2050435ba64SSiva Durga Prasad Paladugu * For BL32, get the chip id info directly by reading corresponding 2060435ba64SSiva Durga Prasad Paladugu * registers instead of making pm call. This has limitation 2070435ba64SSiva Durga Prasad Paladugu * that these registers should be configured to have access 2080435ba64SSiva Durga Prasad Paladugu * from APU which is default case. 2090435ba64SSiva Durga Prasad Paladugu */ 2100435ba64SSiva Durga Prasad Paladugu chipid[0] = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 2110435ba64SSiva Durga Prasad Paladugu chipid[1] = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET); 2120435ba64SSiva Durga Prasad Paladugu #else 2130435ba64SSiva Durga Prasad Paladugu if (pm_get_chipid(chipid) != PM_RET_SUCCESS) 21491bf4c5cSSiva Durga Prasad Paladugu return "UNKN"; 2150435ba64SSiva Durga Prasad Paladugu #endif 21691bf4c5cSSiva Durga Prasad Paladugu 21791bf4c5cSSiva Durga Prasad Paladugu id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 21891bf4c5cSSiva Durga Prasad Paladugu ZYNQMP_CSU_IDCODE_SVD_MASK); 21991bf4c5cSSiva Durga Prasad Paladugu id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 22091bf4c5cSSiva Durga Prasad Paladugu ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT; 221915d4872SSiva Durga Prasad Paladugu 222915d4872SSiva Durga Prasad Paladugu for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 22391bf4c5cSSiva Durga Prasad Paladugu if (zynqmp_devices[i].id == id && 22491bf4c5cSSiva Durga Prasad Paladugu zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK)) 22591bf4c5cSSiva Durga Prasad Paladugu break; 226c8284409SSoren Brinkmann } 22791bf4c5cSSiva Durga Prasad Paladugu 22891bf4c5cSSiva Durga Prasad Paladugu if (i >= ARRAY_SIZE(zynqmp_devices)) 229c8284409SSoren Brinkmann return "UNKN"; 23091bf4c5cSSiva Durga Prasad Paladugu 23191bf4c5cSSiva Durga Prasad Paladugu if (!zynqmp_devices[i].evexists) 23291bf4c5cSSiva Durga Prasad Paladugu return zynqmp_devices[i].name; 23391bf4c5cSSiva Durga Prasad Paladugu 23491bf4c5cSSiva Durga Prasad Paladugu if (ver & ZYNQMP_PL_STATUS_MASK) 23591bf4c5cSSiva Durga Prasad Paladugu return zynqmp_devices[i].name; 23691bf4c5cSSiva Durga Prasad Paladugu 23791bf4c5cSSiva Durga Prasad Paladugu len = strlen(zynqmp_devices[i].name) - 2; 23891bf4c5cSSiva Durga Prasad Paladugu for (j = 0; j < strlen(name); j++) { 23991bf4c5cSSiva Durga Prasad Paladugu zynqmp_devices[i].name[len] = name[j]; 24091bf4c5cSSiva Durga Prasad Paladugu len++; 24191bf4c5cSSiva Durga Prasad Paladugu } 24291bf4c5cSSiva Durga Prasad Paladugu zynqmp_devices[i].name[len] = '\0'; 24391bf4c5cSSiva Durga Prasad Paladugu 24491bf4c5cSSiva Durga Prasad Paladugu return zynqmp_devices[i].name; 245c8284409SSoren Brinkmann } 246c8284409SSoren Brinkmann 247c8284409SSoren Brinkmann static unsigned int zynqmp_get_rtl_ver(void) 248c8284409SSoren Brinkmann { 249c8284409SSoren Brinkmann uint32_t ver; 250c8284409SSoren Brinkmann 251c8284409SSoren Brinkmann ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 252c8284409SSoren Brinkmann ver &= ZYNQMP_RTL_VER_MASK; 253c8284409SSoren Brinkmann ver >>= ZYNQMP_RTL_VER_SHIFT; 254c8284409SSoren Brinkmann 255c8284409SSoren Brinkmann return ver; 256c8284409SSoren Brinkmann } 257c8284409SSoren Brinkmann 258c8284409SSoren Brinkmann static char *zynqmp_print_silicon_idcode(void) 259c8284409SSoren Brinkmann { 260c8284409SSoren Brinkmann uint32_t id, maskid, tmp; 261c8284409SSoren Brinkmann 262c8284409SSoren Brinkmann id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); 263c8284409SSoren Brinkmann 264c8284409SSoren Brinkmann tmp = id; 265c8284409SSoren Brinkmann tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | 266648fe99eSSoren Brinkmann ZYNQMP_CSU_IDCODE_FAMILY_MASK; 267c8284409SSoren Brinkmann maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | 268648fe99eSSoren Brinkmann ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT; 269c8284409SSoren Brinkmann if (tmp != maskid) { 270c8284409SSoren Brinkmann ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid); 271c8284409SSoren Brinkmann return "UNKN"; 272c8284409SSoren Brinkmann } 273c8284409SSoren Brinkmann VERBOSE("Xilinx IDCODE 0x%x\n", id); 274c8284409SSoren Brinkmann return zynqmp_get_silicon_idcode_name(); 275c8284409SSoren Brinkmann } 276c8284409SSoren Brinkmann 277c8284409SSoren Brinkmann static unsigned int zynqmp_get_ps_ver(void) 278c8284409SSoren Brinkmann { 279c8284409SSoren Brinkmann uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); 280c8284409SSoren Brinkmann 281c8284409SSoren Brinkmann ver &= ZYNQMP_PS_VER_MASK; 282c8284409SSoren Brinkmann ver >>= ZYNQMP_PS_VER_SHIFT; 283c8284409SSoren Brinkmann 284c8284409SSoren Brinkmann return ver + 1; 285c8284409SSoren Brinkmann } 286c8284409SSoren Brinkmann 287c8284409SSoren Brinkmann static void zynqmp_print_platform_name(void) 288c8284409SSoren Brinkmann { 289c8284409SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 290c8284409SSoren Brinkmann unsigned int rtl = zynqmp_get_rtl_ver(); 291c8284409SSoren Brinkmann char *label = "Unknown"; 292c8284409SSoren Brinkmann 293c8284409SSoren Brinkmann switch (ver) { 294c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_QEMU: 295c8284409SSoren Brinkmann label = "QEMU"; 296c8284409SSoren Brinkmann break; 297c8284409SSoren Brinkmann case ZYNQMP_CSU_VERSION_SILICON: 298c8284409SSoren Brinkmann label = "silicon"; 299c8284409SSoren Brinkmann break; 300649c48f5SJonathan Wright default: 301649c48f5SJonathan Wright /* Do nothing in default case */ 302649c48f5SJonathan Wright break; 303c8284409SSoren Brinkmann } 304c8284409SSoren Brinkmann 305a6d28520SSiva Durga Prasad Paladugu NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x\n", 306c8284409SSoren Brinkmann zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(), 307a6d28520SSiva Durga Prasad Paladugu (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE); 308c8284409SSoren Brinkmann } 309c8284409SSoren Brinkmann #else 310c8284409SSoren Brinkmann static inline void zynqmp_print_platform_name(void) { } 311c8284409SSoren Brinkmann #endif 312c8284409SSoren Brinkmann 3132cb5bac9SSoren Brinkmann unsigned int zynqmp_get_bootmode(void) 3142cb5bac9SSoren Brinkmann { 31529bd0e66SSiva Durga Prasad Paladugu uint32_t r; 316a6d28520SSiva Durga Prasad Paladugu unsigned int ret; 31729bd0e66SSiva Durga Prasad Paladugu 318a6d28520SSiva Durga Prasad Paladugu ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r); 319a6d28520SSiva Durga Prasad Paladugu 320a6d28520SSiva Durga Prasad Paladugu if (ret != PM_RET_SUCCESS) 32129bd0e66SSiva Durga Prasad Paladugu r = mmio_read_32(CRL_APB_BOOT_MODE_USER); 3222cb5bac9SSoren Brinkmann 3232cb5bac9SSoren Brinkmann return r & CRL_APB_BOOT_MODE_MASK; 3242cb5bac9SSoren Brinkmann } 3252cb5bac9SSoren Brinkmann 326c8284409SSoren Brinkmann void zynqmp_config_setup(void) 327c8284409SSoren Brinkmann { 328c8284409SSoren Brinkmann zynqmp_print_platform_name(); 329e1cb4da4SSoren Brinkmann generic_delay_timer_init(); 330c8284409SSoren Brinkmann } 331c8284409SSoren Brinkmann 332f3d3b316SAntonio Nino Diaz unsigned int plat_get_syscnt_freq2(void) 333c8284409SSoren Brinkmann { 334e89f4af7SSoren Brinkmann unsigned int ver = zynqmp_get_silicon_ver(); 335c8284409SSoren Brinkmann 336976c2680SSiva Durga Prasad Paladugu if (ver == ZYNQMP_CSU_VERSION_QEMU) 337e89f4af7SSoren Brinkmann return 50000000; 338976c2680SSiva Durga Prasad Paladugu else 339e89f4af7SSoren Brinkmann return mmio_read_32(IOU_SCNTRS_BASEFREQ); 340c8284409SSoren Brinkmann } 341