Home | History | Annotate | Download | only in aarch64
      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