xref: /linux/drivers/soc/tegra/fuse/tegra-apbmisc.c (revision 2e51c645fee243dbcb5cee3eb063b5713317444c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014-2023, NVIDIA CORPORATION.  All rights reserved.
4  */
5 
6 #include <linux/acpi.h>
7 #include <linux/arm-smccc.h>
8 #include <linux/export.h>
9 #include <linux/io.h>
10 #include <linux/kernel.h>
11 #include <linux/of.h>
12 #include <linux/of_address.h>
13 
14 #include <soc/tegra/common.h>
15 #include <soc/tegra/fuse.h>
16 
17 #include "fuse.h"
18 
19 #define FUSE_SKU_INFO	0x10
20 
21 #define ERD_ERR_CONFIG 0x120c
22 #define ERD_MASK_INBAND_ERR 0x1
23 
24 #define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT	4
25 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG	\
26 	(0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
27 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT	\
28 	(0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
29 
30 #define TEGRA_SMCCC_PLATFORM(x)		(((x) >> 8) & 0xff)
31 #define TEGRA_SMCCC_CHIP_ID(x)		(((x) >> 4) & 0xff)
32 #define TEGRA_SMCCC_MAJOR_REV(x)	((x) & 0xf)
33 #define TEGRA_SMCCC_MINOR_REV(x)	((x) & 0xf)
34 
35 static void __iomem *apbmisc_base;
36 static bool long_ram_code;
37 static u32 strapping;
38 static u32 chipid;
39 
40 u32 tegra_read_chipid(void)
41 {
42 	WARN(!apbmisc_base, "Tegra APB MISC not yet available\n");
43 
44 	if (!chipid)
45 		chipid = readl_relaxed(apbmisc_base + 4);
46 
47 	return chipid;
48 }
49 
50 u8 tegra_get_chip_id(void)
51 {
52 #if IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY)
53 	s32 soc_id = arm_smccc_get_soc_id_version();
54 
55 	if (soc_id >= 0)
56 		return TEGRA_SMCCC_CHIP_ID(soc_id);
57 #endif
58 	return (tegra_read_chipid() >> 8) & 0xff;
59 }
60 
61 u8 tegra_get_major_rev(void)
62 {
63 #if IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY)
64 	s32 soc_id = arm_smccc_get_soc_id_version();
65 
66 	if (soc_id >= 0)
67 		return TEGRA_SMCCC_MAJOR_REV(soc_id);
68 #endif
69 	return (tegra_read_chipid() >> 4) & 0xf;
70 }
71 
72 u8 tegra_get_minor_rev(void)
73 {
74 #if IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY)
75 	s32 revision = arm_smccc_get_soc_id_revision();
76 
77 	if (revision >= 0)
78 		return TEGRA_SMCCC_MINOR_REV(revision);
79 #endif
80 	return (tegra_read_chipid() >> 16) & 0xf;
81 
82 }
83 
84 u8 tegra_get_platform(void)
85 {
86 #if IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY)
87 	s32 revision = arm_smccc_get_soc_id_revision();
88 
89 	if (revision >= 0)
90 		return TEGRA_SMCCC_PLATFORM(revision);
91 #endif
92 	return (tegra_read_chipid() >> 20) & 0xf;
93 }
94 
95 bool tegra_is_silicon(void)
96 {
97 	switch (tegra_get_chip_id()) {
98 	case TEGRA194:
99 	case TEGRA234:
100 	case TEGRA241:
101 	case TEGRA264:
102 		if (tegra_get_platform() == 0)
103 			return true;
104 
105 		return false;
106 	}
107 
108 	/*
109 	 * Chips prior to Tegra194 have a different way of determining whether
110 	 * they are silicon or not. Since we never supported simulation on the
111 	 * older Tegra chips, don't bother extracting the information and just
112 	 * report that we're running on silicon.
113 	 */
114 	return true;
115 }
116 
117 u32 tegra_read_straps(void)
118 {
119 	WARN(!apbmisc_base, "Tegra ABP MISC not yet available\n");
120 
121 	return strapping;
122 }
123 
124 u32 tegra_read_ram_code(void)
125 {
126 	u32 straps = tegra_read_straps();
127 
128 	if (long_ram_code)
129 		straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG;
130 	else
131 		straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT;
132 
133 	return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT;
134 }
135 EXPORT_SYMBOL_GPL(tegra_read_ram_code);
136 
137 /*
138  * The function sets ERD(Error Response Disable) bit.
139  * This allows to mask inband errors and always send an
140  * OKAY response from CBB to the master which caused error.
141  */
142 int tegra194_miscreg_mask_serror(void)
143 {
144 	if (!apbmisc_base)
145 		return -EPROBE_DEFER;
146 
147 	if (!of_machine_is_compatible("nvidia,tegra194")) {
148 		WARN(1, "Only supported for Tegra194 devices!\n");
149 		return -EOPNOTSUPP;
150 	}
151 
152 	writel_relaxed(ERD_MASK_INBAND_ERR,
153 		       apbmisc_base + ERD_ERR_CONFIG);
154 
155 	return 0;
156 }
157 EXPORT_SYMBOL(tegra194_miscreg_mask_serror);
158 
159 static const struct of_device_id apbmisc_match[] __initconst = {
160 	{ .compatible = "nvidia,tegra20-apbmisc", },
161 	{ .compatible = "nvidia,tegra186-misc", },
162 	{ .compatible = "nvidia,tegra194-misc", },
163 	{ .compatible = "nvidia,tegra234-misc", },
164 	{ .compatible = "nvidia,tegra264-misc", },
165 	{},
166 };
167 
168 void __init tegra_init_revision(void)
169 {
170 	u8 chip_id, major_rev, minor_rev;
171 
172 	chip_id = tegra_get_chip_id();
173 	major_rev = tegra_get_major_rev();
174 	minor_rev = tegra_get_minor_rev();
175 
176 	if (major_rev > 1) {
177 		switch (minor_rev) {
178 		case 1:
179 			tegra_sku_info.revision = TEGRA_REVISION_B01;
180 			break;
181 		default:
182 			tegra_sku_info.revision = TEGRA_REVISION_UNKNOWN;
183 		}
184 	} else {
185 		switch (minor_rev) {
186 		case 1:
187 			tegra_sku_info.revision = TEGRA_REVISION_A01;
188 			break;
189 		case 2:
190 			tegra_sku_info.revision = TEGRA_REVISION_A02;
191 			break;
192 		case 3:
193 			if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) ||
194 						   tegra_fuse_read_spare(19)))
195 				tegra_sku_info.revision = TEGRA_REVISION_A03p;
196 			else
197 				tegra_sku_info.revision = TEGRA_REVISION_A03;
198 			break;
199 		case 4:
200 			tegra_sku_info.revision = TEGRA_REVISION_A04;
201 			break;
202 		default:
203 			tegra_sku_info.revision = TEGRA_REVISION_UNKNOWN;
204 		}
205 	}
206 
207 	tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO);
208 	tegra_sku_info.platform = tegra_get_platform();
209 }
210 
211 static void tegra_init_apbmisc_resources(struct resource *apbmisc,
212 					 struct resource *straps)
213 {
214 	void __iomem *strapping_base;
215 
216 	apbmisc_base = ioremap(apbmisc->start, resource_size(apbmisc));
217 	if (!apbmisc_base)
218 		pr_err("failed to map APBMISC registers\n");
219 
220 	strapping_base = ioremap(straps->start, resource_size(straps));
221 	if (strapping_base) {
222 		strapping = readl_relaxed(strapping_base);
223 		iounmap(strapping_base);
224 	} else {
225 		pr_err("failed to map strapping options registers\n");
226 	}
227 }
228 
229 /**
230  * tegra_init_apbmisc - Initializes Tegra APBMISC and Strapping registers.
231  *
232  * This is called during early init as some of the old 32-bit ARM code needs
233  * information from the APBMISC registers very early during boot.
234  */
235 void __init tegra_init_apbmisc(void)
236 {
237 	struct resource apbmisc, straps;
238 	struct device_node *np;
239 
240 	np = of_find_matching_node(NULL, apbmisc_match);
241 	if (!np) {
242 		/*
243 		 * Fall back to legacy initialization for 32-bit ARM only. All
244 		 * 64-bit ARM device tree files for Tegra are required to have
245 		 * an APBMISC node.
246 		 *
247 		 * This is for backwards-compatibility with old device trees
248 		 * that didn't contain an APBMISC node.
249 		 */
250 		if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
251 			/* APBMISC registers (chip revision, ...) */
252 			apbmisc.start = 0x70000800;
253 			apbmisc.end = 0x70000863;
254 			apbmisc.flags = IORESOURCE_MEM;
255 
256 			/* strapping options */
257 			if (of_machine_is_compatible("nvidia,tegra124")) {
258 				straps.start = 0x7000e864;
259 				straps.end = 0x7000e867;
260 			} else {
261 				straps.start = 0x70000008;
262 				straps.end = 0x7000000b;
263 			}
264 
265 			straps.flags = IORESOURCE_MEM;
266 
267 			pr_warn("Using APBMISC region %pR\n", &apbmisc);
268 			pr_warn("Using strapping options registers %pR\n",
269 				&straps);
270 		} else {
271 			/*
272 			 * At this point we're not running on Tegra, so play
273 			 * nice with multi-platform kernels.
274 			 */
275 			return;
276 		}
277 	} else {
278 		/*
279 		 * Extract information from the device tree if we've found a
280 		 * matching node.
281 		 */
282 		if (of_address_to_resource(np, 0, &apbmisc) < 0) {
283 			pr_err("failed to get APBMISC registers\n");
284 			goto put;
285 		}
286 
287 		if (of_address_to_resource(np, 1, &straps) < 0) {
288 			pr_err("failed to get strapping options registers\n");
289 			goto put;
290 		}
291 	}
292 
293 	tegra_init_apbmisc_resources(&apbmisc, &straps);
294 	long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code");
295 
296 put:
297 	of_node_put(np);
298 }
299 
300 #ifdef CONFIG_ACPI
301 static const struct acpi_device_id apbmisc_acpi_match[] = {
302 	{ "NVDA2010" },
303 	{ /* sentinel */ }
304 };
305 
306 void tegra_acpi_init_apbmisc(void)
307 {
308 	struct resource *resources[2] = { NULL };
309 	struct resource_entry *rentry;
310 	struct acpi_device *adev = NULL;
311 	struct list_head resource_list;
312 	int rcount = 0;
313 	int ret;
314 
315 	adev = acpi_dev_get_first_match_dev(apbmisc_acpi_match[0].id, NULL, -1);
316 	if (!adev)
317 		return;
318 
319 	INIT_LIST_HEAD(&resource_list);
320 
321 	ret = acpi_dev_get_memory_resources(adev, &resource_list);
322 	if (ret < 0) {
323 		pr_err("failed to get APBMISC memory resources\n");
324 		goto out_put_acpi_dev;
325 	}
326 
327 	/*
328 	 * Get required memory resources.
329 	 *
330 	 * resources[0]: apbmisc.
331 	 * resources[1]: straps.
332 	 */
333 	resource_list_for_each_entry(rentry, &resource_list) {
334 		if (rcount >= ARRAY_SIZE(resources))
335 			break;
336 
337 		resources[rcount++] = rentry->res;
338 	}
339 
340 	if (!resources[0]) {
341 		pr_err("failed to get APBMISC registers\n");
342 		goto out_free_resource_list;
343 	}
344 
345 	if (!resources[1]) {
346 		pr_err("failed to get strapping options registers\n");
347 		goto out_free_resource_list;
348 	}
349 
350 	tegra_init_apbmisc_resources(resources[0], resources[1]);
351 
352 out_free_resource_list:
353 	acpi_dev_free_resource_list(&resource_list);
354 
355 out_put_acpi_dev:
356 	acpi_dev_put(adev);
357 }
358 #else
359 void tegra_acpi_init_apbmisc(void)
360 {
361 }
362 #endif
363