• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
zynqmp_get_silicon_ver(void)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 
zynqmp_get_uart_clk(void)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 
zynqmp_get_silicon_id(void)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 
zynqmp_get_silicon_idcode_name(void)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 
zynqmp_get_rtl_ver(void)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 
zynqmp_print_silicon_idcode(void)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 
zynqmp_get_ps_ver(void)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 
zynqmp_print_platform_name(void)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
zynqmp_print_platform_name(void)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  */
zynqmp_discover_pmufw(void)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  */
zynqmp_is_pmu_up(void)231 int zynqmp_is_pmu_up(void)
232 {
233 	return zynqmp_pmufw_present;
234 }
235 
zynqmp_get_bootmode(void)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 
zynqmp_config_setup(void)243 void zynqmp_config_setup(void)
244 {
245 	zynqmp_discover_pmufw();
246 	zynqmp_print_platform_name();
247 	generic_delay_timer_init();
248 }
249 
plat_get_syscnt_freq2(void)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