1 /*
2 * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
3 * Copyright (c) 2020-2023, NVIDIA Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <arch_helpers.h>
9 #include <assert.h>
10 #include <lib/mmio.h>
11 #include <lib/smccc.h>
12 #include <services/arm_arch_svc.h>
13 #include <tegra_def.h>
14 #include <tegra_platform.h>
15 #include <tegra_private.h>
16
17 /*******************************************************************************
18 * Tegra platforms
19 ******************************************************************************/
20 typedef enum tegra_platform {
21 TEGRA_PLATFORM_SILICON = 0U,
22 TEGRA_PLATFORM_QT,
23 TEGRA_PLATFORM_FPGA,
24 TEGRA_PLATFORM_EMULATION,
25 TEGRA_PLATFORM_LINSIM,
26 TEGRA_PLATFORM_UNIT_FPGA,
27 TEGRA_PLATFORM_VIRT_DEV_KIT,
28 TEGRA_PLATFORM_MAX,
29 } tegra_platform_t;
30
31 /*******************************************************************************
32 * Tegra macros defining all the SoC minor versions
33 ******************************************************************************/
34 #define TEGRA_MINOR_QT U(0)
35 #define TEGRA_MINOR_FPGA U(1)
36 #define TEGRA_MINOR_ASIM_QT U(2)
37 #define TEGRA_MINOR_ASIM_LINSIM U(3)
38 #define TEGRA_MINOR_DSIM_ASIM_LINSIM U(4)
39 #define TEGRA_MINOR_UNIT_FPGA U(5)
40 #define TEGRA_MINOR_VIRT_DEV_KIT U(6)
41
42 /*******************************************************************************
43 * Tegra macros defining all the SoC pre_si_platform
44 ******************************************************************************/
45 #define TEGRA_PRE_SI_QT U(1)
46 #define TEGRA_PRE_SI_FPGA U(2)
47 #define TEGRA_PRE_SI_UNIT_FPGA U(3)
48 #define TEGRA_PRE_SI_ASIM_QT U(4)
49 #define TEGRA_PRE_SI_ASIM_LINSIM U(5)
50 #define TEGRA_PRE_SI_DSIM_ASIM_LINSIM U(6)
51 #define TEGRA_PRE_SI_VDK U(8)
52
53 /*
54 * Read the chip ID value
55 */
tegra_get_chipid(void)56 static uint32_t tegra_get_chipid(void)
57 {
58 return mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET);
59 }
60
61 /*
62 * Read the chip's major version from chip ID value
63 */
tegra_get_chipid_major(void)64 uint32_t tegra_get_chipid_major(void)
65 {
66 return (tegra_get_chipid() >> MAJOR_VERSION_SHIFT) & MAJOR_VERSION_MASK;
67 }
68
69 /*
70 * Read the chip's minor version from the chip ID value
71 */
tegra_get_chipid_minor(void)72 uint32_t tegra_get_chipid_minor(void)
73 {
74 return (tegra_get_chipid() >> MINOR_VERSION_SHIFT) & MINOR_VERSION_MASK;
75 }
76
77 /*
78 * Read the chip's pre_si_platform valus from the chip ID value
79 */
tegra_get_chipid_pre_si_platform(void)80 static uint32_t tegra_get_chipid_pre_si_platform(void)
81 {
82 return (tegra_get_chipid() >> PRE_SI_PLATFORM_SHIFT) & PRE_SI_PLATFORM_MASK;
83 }
84
tegra_chipid_is_t194(void)85 bool tegra_chipid_is_t194(void)
86 {
87 uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK;
88
89 return (chip_id == TEGRA_CHIPID_TEGRA19);
90 }
91
92 /*
93 * Read the chip ID value and derive the platform
94 */
tegra_get_platform(void)95 static tegra_platform_t tegra_get_platform(void)
96 {
97 uint32_t major, minor, pre_si_platform;
98 tegra_platform_t ret;
99
100 /* get the major/minor chip ID values */
101 major = tegra_get_chipid_major();
102 minor = tegra_get_chipid_minor();
103 pre_si_platform = tegra_get_chipid_pre_si_platform();
104
105 if (major == 0U) {
106 /*
107 * The minor version number is used by simulation platforms
108 */
109 switch (minor) {
110 /*
111 * Cadence's QuickTurn emulation system is a Solaris-based
112 * chip emulation system
113 */
114 case TEGRA_MINOR_QT:
115 case TEGRA_MINOR_ASIM_QT:
116 ret = TEGRA_PLATFORM_QT;
117 break;
118
119 /*
120 * FPGAs are used during early software/hardware development
121 */
122 case TEGRA_MINOR_FPGA:
123 ret = TEGRA_PLATFORM_FPGA;
124 break;
125 /*
126 * Linsim is a reconfigurable, clock-driven, mixed RTL/cmodel
127 * simulation framework.
128 */
129 case TEGRA_MINOR_ASIM_LINSIM:
130 case TEGRA_MINOR_DSIM_ASIM_LINSIM:
131 ret = TEGRA_PLATFORM_LINSIM;
132 break;
133
134 /*
135 * Unit FPGAs run the actual hardware block IP on the FPGA with
136 * the other parts of the system using Linsim.
137 */
138 case TEGRA_MINOR_UNIT_FPGA:
139 ret = TEGRA_PLATFORM_UNIT_FPGA;
140 break;
141 /*
142 * The Virtualizer Development Kit (VDK) is the standard chip
143 * development from Synopsis.
144 */
145 case TEGRA_MINOR_VIRT_DEV_KIT:
146 ret = TEGRA_PLATFORM_VIRT_DEV_KIT;
147 break;
148
149 default:
150 ret = TEGRA_PLATFORM_MAX;
151 break;
152 }
153
154 } else if (pre_si_platform > 0U) {
155
156 switch (pre_si_platform) {
157 /*
158 * Cadence's QuickTurn emulation system is a Solaris-based
159 * chip emulation system
160 */
161 case TEGRA_PRE_SI_QT:
162 case TEGRA_PRE_SI_ASIM_QT:
163 ret = TEGRA_PLATFORM_QT;
164 break;
165
166 /*
167 * FPGAs are used during early software/hardware development
168 */
169 case TEGRA_PRE_SI_FPGA:
170 ret = TEGRA_PLATFORM_FPGA;
171 break;
172 /*
173 * Linsim is a reconfigurable, clock-driven, mixed RTL/cmodel
174 * simulation framework.
175 */
176 case TEGRA_PRE_SI_ASIM_LINSIM:
177 case TEGRA_PRE_SI_DSIM_ASIM_LINSIM:
178 ret = TEGRA_PLATFORM_LINSIM;
179 break;
180
181 /*
182 * Unit FPGAs run the actual hardware block IP on the FPGA with
183 * the other parts of the system using Linsim.
184 */
185 case TEGRA_PRE_SI_UNIT_FPGA:
186 ret = TEGRA_PLATFORM_UNIT_FPGA;
187 break;
188 /*
189 * The Virtualizer Development Kit (VDK) is the standard chip
190 * development from Synopsis.
191 */
192 case TEGRA_PRE_SI_VDK:
193 ret = TEGRA_PLATFORM_VIRT_DEV_KIT;
194 break;
195
196 default:
197 ret = TEGRA_PLATFORM_MAX;
198 break;
199 }
200
201 } else {
202 /* Actual silicon platforms have a non-zero major version */
203 ret = TEGRA_PLATFORM_SILICON;
204 }
205
206 return ret;
207 }
208
tegra_platform_is_silicon(void)209 bool tegra_platform_is_silicon(void)
210 {
211 return ((tegra_get_platform() == TEGRA_PLATFORM_SILICON) ? true : false);
212 }
213
tegra_platform_is_qt(void)214 bool tegra_platform_is_qt(void)
215 {
216 return ((tegra_get_platform() == TEGRA_PLATFORM_QT) ? true : false);
217 }
218
tegra_platform_is_linsim(void)219 bool tegra_platform_is_linsim(void)
220 {
221 tegra_platform_t plat = tegra_get_platform();
222
223 return (((plat == TEGRA_PLATFORM_LINSIM) ||
224 (plat == TEGRA_PLATFORM_UNIT_FPGA)) ? true : false);
225 }
226
tegra_platform_is_fpga(void)227 bool tegra_platform_is_fpga(void)
228 {
229 return ((tegra_get_platform() == TEGRA_PLATFORM_FPGA) ? true : false);
230 }
231
tegra_platform_is_emulation(void)232 bool tegra_platform_is_emulation(void)
233 {
234 return (tegra_get_platform() == TEGRA_PLATFORM_EMULATION);
235 }
236
tegra_platform_is_unit_fpga(void)237 bool tegra_platform_is_unit_fpga(void)
238 {
239 return ((tegra_get_platform() == TEGRA_PLATFORM_UNIT_FPGA) ? true : false);
240 }
241
tegra_platform_is_virt_dev_kit(void)242 bool tegra_platform_is_virt_dev_kit(void)
243 {
244 return ((tegra_get_platform() == TEGRA_PLATFORM_VIRT_DEV_KIT) ? true : false);
245 }
246
247 /*
248 * This function returns soc version which mainly consist of below fields
249 *
250 * soc_version[30:24] = JEP-106 continuation code for the SiP
251 * soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
252 * soc_version[0:15] = chip identification
253 */
plat_get_soc_version(void)254 int32_t plat_get_soc_version(void)
255 {
256 uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK;
257 uint32_t major_rev = tegra_get_chipid_major();
258 uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_NVIDIA_BKID, JEDEC_NVIDIA_MFID);
259
260 return (int32_t)(manfid | (((chip_id << MAJOR_VERSION_SHIFT) | major_rev) &
261 SOC_ID_IMPL_DEF_MASK));
262 }
263
264 /*
265 * This function returns soc revision in below format
266 *
267 * soc_revision[8:15] = major version number
268 * soc_revision[0:7] = minor version number
269 */
plat_get_soc_revision(void)270 int32_t plat_get_soc_revision(void)
271 {
272 return (int32_t)(((tegra_get_chipid_major() << 8) | tegra_get_chipid_minor()) &
273 SOC_ID_REV_MASK);
274 }
275
276 /*****************************************************************************
277 * plat_is_smccc_feature_available() - This function checks whether SMCCC feature
278 * is availabile for the platform or not.
279 * @fid: SMCCC function id
280 *
281 * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
282 * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
283 *****************************************************************************/
plat_is_smccc_feature_available(u_register_t fid)284 int32_t plat_is_smccc_feature_available(u_register_t fid)
285 {
286 switch (fid) {
287 case SMCCC_ARCH_SOC_ID:
288 return SMC_ARCH_CALL_SUCCESS;
289 default:
290 return SMC_ARCH_CALL_NOT_SUPPORTED;
291 }
292 }
293