diff options
Diffstat (limited to 'arch/arm/mach-tegra/fuse.c')
-rw-r--r-- | arch/arm/mach-tegra/fuse.c | 423 |
1 files changed, 400 insertions, 23 deletions
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index 1fa26d9a1a6..d9fe1b02d0e 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * arch/arm/mach-tegra/fuse.c | 2 | * arch/arm/mach-tegra/fuse.c |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Google, Inc. | 4 | * Copyright (C) 2010 Google, Inc. |
5 | * Copyright (C) 2010-2011 NVIDIA Corp. | ||
5 | * | 6 | * |
6 | * Author: | 7 | * Author: |
7 | * Colin Cross <ccross@android.com> | 8 | * Colin Cross <ccross@android.com> |
@@ -19,24 +20,87 @@ | |||
19 | 20 | ||
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/init.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/moduleparam.h> | ||
22 | 27 | ||
23 | #include <mach/iomap.h> | 28 | #include <mach/iomap.h> |
29 | #include <mach/tegra_fuse.h> | ||
24 | 30 | ||
25 | #include "fuse.h" | 31 | #include "fuse.h" |
32 | #include "apbio.h" | ||
26 | 33 | ||
34 | #define FUSE_SKU_INFO 0x110 | ||
35 | #if defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
27 | #define FUSE_UID_LOW 0x108 | 36 | #define FUSE_UID_LOW 0x108 |
28 | #define FUSE_UID_HIGH 0x10c | 37 | #define FUSE_UID_HIGH 0x10c |
29 | #define FUSE_SKU_INFO 0x110 | ||
30 | #define FUSE_SPARE_BIT 0x200 | 38 | #define FUSE_SPARE_BIT 0x200 |
39 | #else | ||
40 | #define FUSE_VENDOR_CODE 0x200 | ||
41 | #define FUSE_VENDOR_CODE_MASK 0xf | ||
42 | #define FUSE_FAB_CODE 0x204 | ||
43 | #define FUSE_FAB_CODE_MASK 0x3f | ||
44 | #define FUSE_LOT_CODE_0 0x208 | ||
45 | #define FUSE_LOT_CODE_1 0x20c | ||
46 | #define FUSE_WAFER_ID 0x210 | ||
47 | #define FUSE_WAFER_ID_MASK 0x3f | ||
48 | #define FUSE_X_COORDINATE 0x214 | ||
49 | #define FUSE_X_COORDINATE_MASK 0x1ff | ||
50 | #define FUSE_Y_COORDINATE 0x218 | ||
51 | #define FUSE_Y_COORDINATE_MASK 0x1ff | ||
52 | #define FUSE_GPU_INFO 0x390 | ||
53 | #define FUSE_GPU_INFO_MASK (1<<2) | ||
54 | #define FUSE_SPARE_BIT 0x244 | ||
55 | /* fuse registers used in public fuse data read API */ | ||
56 | #define FUSE_TEST_PROGRAM_REVISION_0 0x128 | ||
57 | /* fuse spare bits are used to get Tj-ADT values */ | ||
58 | #define FUSE_SPARE_BIT_0_0 0x244 | ||
59 | #define NUM_TSENSOR_SPARE_BITS 28 | ||
60 | /* tsensor calibration register */ | ||
61 | #define FUSE_TSENSOR_CALIB_0 0x198 | ||
62 | |||
63 | #endif | ||
64 | |||
65 | struct tegra_id { | ||
66 | enum tegra_chipid chipid; | ||
67 | unsigned int major, minor, netlist, patch; | ||
68 | enum tegra_revision revision; | ||
69 | char *priv; | ||
70 | }; | ||
71 | |||
72 | static struct tegra_id tegra_id; | ||
73 | static unsigned int tegra_chip_id; | ||
74 | static unsigned int tegra_chip_rev; | ||
75 | |||
76 | static const char *tegra_revision_name[TEGRA_REVISION_MAX] = { | ||
77 | [TEGRA_REVISION_UNKNOWN] = "unknown", | ||
78 | [TEGRA_REVISION_A01] = "A01", | ||
79 | [TEGRA_REVISION_A02] = "A02", | ||
80 | [TEGRA_REVISION_A03] = "A03", | ||
81 | [TEGRA_REVISION_A03p] = "A03 prime", | ||
82 | [TEGRA_REVISION_A04] = "A04", | ||
83 | [TEGRA_REVISION_A04p] = "A04 prime", | ||
84 | }; | ||
85 | |||
86 | u32 tegra_fuse_readl(unsigned long offset) | ||
87 | { | ||
88 | return tegra_apb_readl(TEGRA_FUSE_BASE + offset); | ||
89 | } | ||
90 | |||
91 | void tegra_fuse_writel(u32 value, unsigned long offset) | ||
92 | { | ||
93 | tegra_apb_writel(value, TEGRA_FUSE_BASE + offset); | ||
94 | } | ||
31 | 95 | ||
32 | static inline u32 fuse_readl(unsigned long offset) | 96 | static inline bool get_spare_fuse(int bit) |
33 | { | 97 | { |
34 | return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); | 98 | return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4); |
35 | } | 99 | } |
36 | 100 | ||
37 | static inline void fuse_writel(u32 value, unsigned long offset) | 101 | const char *tegra_get_revision_name(void) |
38 | { | 102 | { |
39 | writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); | 103 | return tegra_revision_name[tegra_get_revision()]; |
40 | } | 104 | } |
41 | 105 | ||
42 | void tegra_init_fuse(void) | 106 | void tegra_init_fuse(void) |
@@ -44,41 +108,354 @@ void tegra_init_fuse(void) | |||
44 | u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); | 108 | u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); |
45 | reg |= 1 << 28; | 109 | reg |= 1 << 28; |
46 | writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); | 110 | writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); |
111 | tegra_init_speedo_data(); | ||
112 | |||
113 | pr_info("Tegra Revision: %s " | ||
114 | "SKU: 0x%x CPU Process: %d Core Process: %d\n", | ||
115 | tegra_get_revision_name(), tegra_sku_id(), | ||
116 | tegra_cpu_process_id(), tegra_core_process_id()); | ||
117 | } | ||
47 | 118 | ||
48 | pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n", | 119 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
49 | tegra_sku_id(), tegra_cpu_process_id(), | 120 | int tegra_fuse_get_revision(u32 *rev) |
50 | tegra_core_process_id()); | 121 | { |
122 | return -ENOENT; | ||
51 | } | 123 | } |
124 | EXPORT_SYMBOL(tegra_fuse_get_revision); | ||
125 | |||
126 | int tegra_fuse_get_tsensor_calibration_data(u32 *calib) | ||
127 | { | ||
128 | return -ENOENT; | ||
129 | } | ||
130 | EXPORT_SYMBOL(tegra_fuse_get_tsensor_calibration_data); | ||
131 | |||
132 | int tegra_fuse_get_tsensor_spare_bits(u32 *spare_bits) | ||
133 | { | ||
134 | return -ENOENT; | ||
135 | } | ||
136 | EXPORT_SYMBOL(tegra_fuse_get_tsensor_spare_bits); | ||
137 | |||
138 | #else | ||
139 | |||
140 | int tegra_fuse_get_revision(u32 *rev) | ||
141 | { | ||
142 | /* fuse revision */ | ||
143 | *rev = tegra_fuse_readl(FUSE_TEST_PROGRAM_REVISION_0); | ||
144 | return 0; | ||
145 | } | ||
146 | EXPORT_SYMBOL(tegra_fuse_get_revision); | ||
147 | |||
148 | int tegra_fuse_get_tsensor_calibration_data(u32 *calib) | ||
149 | { | ||
150 | /* tsensor calibration fuse */ | ||
151 | *calib = tegra_fuse_readl(FUSE_TSENSOR_CALIB_0); | ||
152 | return 0; | ||
153 | } | ||
154 | EXPORT_SYMBOL(tegra_fuse_get_tsensor_calibration_data); | ||
155 | |||
156 | int tegra_fuse_get_tsensor_spare_bits(u32 *spare_bits) | ||
157 | { | ||
158 | u32 value; | ||
159 | int i; | ||
160 | |||
161 | BUG_ON(NUM_TSENSOR_SPARE_BITS > (sizeof(u32) * 8)); | ||
162 | if (!spare_bits) | ||
163 | return -ENOMEM; | ||
164 | *spare_bits = 0; | ||
165 | /* spare bits 0-27 */ | ||
166 | for (i = 0; i < NUM_TSENSOR_SPARE_BITS; i++) { | ||
167 | value = tegra_fuse_readl(FUSE_SPARE_BIT_0_0 + | ||
168 | (i << 2)); | ||
169 | if (value) | ||
170 | *spare_bits |= BIT(i); | ||
171 | } | ||
172 | return 0; | ||
173 | } | ||
174 | EXPORT_SYMBOL(tegra_fuse_get_tsensor_spare_bits); | ||
175 | #endif | ||
52 | 176 | ||
53 | unsigned long long tegra_chip_uid(void) | 177 | unsigned long long tegra_chip_uid(void) |
54 | { | 178 | { |
179 | #if defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
55 | unsigned long long lo, hi; | 180 | unsigned long long lo, hi; |
56 | 181 | ||
57 | lo = fuse_readl(FUSE_UID_LOW); | 182 | lo = tegra_fuse_readl(FUSE_UID_LOW); |
58 | hi = fuse_readl(FUSE_UID_HIGH); | 183 | hi = tegra_fuse_readl(FUSE_UID_HIGH); |
59 | return (hi << 32ull) | lo; | 184 | return (hi << 32ull) | lo; |
185 | #else | ||
186 | u64 uid = 0ull; | ||
187 | u32 reg; | ||
188 | u32 cid; | ||
189 | u32 vendor; | ||
190 | u32 fab; | ||
191 | u32 lot; | ||
192 | u32 wafer; | ||
193 | u32 x; | ||
194 | u32 y; | ||
195 | u32 i; | ||
196 | |||
197 | /* This used to be so much easier in prior chips. Unfortunately, there | ||
198 | is no one-stop shopping for the unique id anymore. It must be | ||
199 | constructed from various bits of information burned into the fuses | ||
200 | during the manufacturing process. The 64-bit unique id is formed | ||
201 | by concatenating several bit fields. The notation used for the | ||
202 | various fields is <fieldname:size_in_bits> with the UID composed | ||
203 | thusly: | ||
204 | |||
205 | <CID:4><VENDOR:4><FAB:6><LOT:26><WAFER:6><X:9><Y:9> | ||
206 | |||
207 | Where: | ||
208 | |||
209 | Field Bits Position Data | ||
210 | ------- ---- -------- ---------------------------------------- | ||
211 | CID 4 60 Chip id (encoded as zero for T30) | ||
212 | VENDOR 4 56 Vendor code | ||
213 | FAB 6 50 FAB code | ||
214 | LOT 26 24 Lot code (5-digit base-36-coded-decimal, | ||
215 | re-encoded to 26 bits binary) | ||
216 | WAFER 6 18 Wafer id | ||
217 | X 9 9 Wafer X-coordinate | ||
218 | Y 9 0 Wafer Y-coordinate | ||
219 | ------- ---- | ||
220 | Total 64 | ||
221 | */ | ||
222 | |||
223 | /* Get the chip id and encode each chip variant as a unique value. */ | ||
224 | reg = readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + 0x804)); | ||
225 | reg = (reg & 0xFF00) >> 8; | ||
226 | |||
227 | switch (reg) { | ||
228 | case TEGRA_CHIPID_TEGRA3: | ||
229 | cid = 0; | ||
230 | break; | ||
231 | |||
232 | default: | ||
233 | BUG(); | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | vendor = tegra_fuse_readl(FUSE_VENDOR_CODE) & FUSE_VENDOR_CODE_MASK; | ||
238 | fab = tegra_fuse_readl(FUSE_FAB_CODE) & FUSE_FAB_CODE_MASK; | ||
239 | |||
240 | /* Lot code must be re-encoded from a 5 digit base-36 'BCD' number | ||
241 | to a binary number. */ | ||
242 | lot = 0; | ||
243 | reg = tegra_fuse_readl(FUSE_LOT_CODE_0) << 2; | ||
244 | |||
245 | for (i = 0; i < 5; ++i) { | ||
246 | u32 digit = (reg & 0xFC000000) >> 26; | ||
247 | BUG_ON(digit >= 36); | ||
248 | lot *= 36; | ||
249 | lot += digit; | ||
250 | reg <<= 6; | ||
251 | } | ||
252 | |||
253 | wafer = tegra_fuse_readl(FUSE_WAFER_ID) & FUSE_WAFER_ID_MASK; | ||
254 | x = tegra_fuse_readl(FUSE_X_COORDINATE) & FUSE_X_COORDINATE_MASK; | ||
255 | y = tegra_fuse_readl(FUSE_Y_COORDINATE) & FUSE_Y_COORDINATE_MASK; | ||
256 | |||
257 | uid = ((unsigned long long)cid << 60ull) | ||
258 | | ((unsigned long long)vendor << 56ull) | ||
259 | | ((unsigned long long)fab << 50ull) | ||
260 | | ((unsigned long long)lot << 24ull) | ||
261 | | ((unsigned long long)wafer << 18ull) | ||
262 | | ((unsigned long long)x << 9ull) | ||
263 | | ((unsigned long long)y << 0ull); | ||
264 | return uid; | ||
265 | #endif | ||
266 | } | ||
267 | |||
268 | unsigned int tegra_spare_fuse(int bit) | ||
269 | { | ||
270 | BUG_ON(bit < 0 || bit > 61); | ||
271 | return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4); | ||
60 | } | 272 | } |
61 | 273 | ||
62 | int tegra_sku_id(void) | 274 | int tegra_sku_id(void) |
63 | { | 275 | { |
64 | int sku_id; | 276 | static int sku_id = -1; |
65 | u32 reg = fuse_readl(FUSE_SKU_INFO); | 277 | if (sku_id == -1) { |
66 | sku_id = reg & 0xFF; | 278 | u32 reg = tegra_fuse_readl(FUSE_SKU_INFO); |
279 | sku_id = reg & 0xFF; | ||
280 | } | ||
67 | return sku_id; | 281 | return sku_id; |
68 | } | 282 | } |
69 | 283 | ||
70 | int tegra_cpu_process_id(void) | 284 | int tegra_gpu_register_sets(void) |
285 | { | ||
286 | #ifdef CONFIG_ARCH_TEGRA_HAS_DUAL_3D | ||
287 | u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + FUSE_GPU_INFO)); | ||
288 | if (reg & FUSE_GPU_INFO_MASK) | ||
289 | return 1; | ||
290 | else | ||
291 | return 2; | ||
292 | #else | ||
293 | return 1; | ||
294 | #endif | ||
295 | } | ||
296 | |||
297 | struct chip_revision { | ||
298 | enum tegra_chipid chipid; | ||
299 | unsigned int major; | ||
300 | unsigned int minor; | ||
301 | char prime; | ||
302 | enum tegra_revision revision; | ||
303 | }; | ||
304 | |||
305 | #define CHIP_REVISION(id, m, n, p, rev) { \ | ||
306 | .chipid = TEGRA_CHIPID_##id, \ | ||
307 | .major = m, \ | ||
308 | .minor = n, \ | ||
309 | .prime = p, \ | ||
310 | .revision = TEGRA_REVISION_##rev } | ||
311 | |||
312 | static struct chip_revision tegra_chip_revisions[] = { | ||
313 | CHIP_REVISION(TEGRA2, 1, 2, 0, A02), | ||
314 | CHIP_REVISION(TEGRA2, 1, 3, 0, A03), | ||
315 | CHIP_REVISION(TEGRA2, 1, 3, 'p', A03p), | ||
316 | CHIP_REVISION(TEGRA2, 1, 4, 0, A04), | ||
317 | CHIP_REVISION(TEGRA2, 1, 4, 'p', A04p), | ||
318 | CHIP_REVISION(TEGRA3, 1, 1, 0, A01), | ||
319 | CHIP_REVISION(TEGRA3, 1, 2, 0, A02), | ||
320 | CHIP_REVISION(TEGRA3, 1, 3, 0, A03), | ||
321 | }; | ||
322 | |||
323 | static enum tegra_revision tegra_decode_revision(const struct tegra_id *id) | ||
324 | { | ||
325 | enum tegra_revision revision = TEGRA_REVISION_UNKNOWN; | ||
326 | |||
327 | #if defined(CONFIG_TEGRA_SILICON_PLATFORM) | ||
328 | int i ; | ||
329 | char prime; | ||
330 | |||
331 | if (id->priv == NULL) | ||
332 | prime = 0; | ||
333 | else | ||
334 | prime = *(id->priv); | ||
335 | |||
336 | for (i = 0; i < ARRAY_SIZE(tegra_chip_revisions); i++) { | ||
337 | if ((id->chipid != tegra_chip_revisions[i].chipid) || | ||
338 | (id->minor != tegra_chip_revisions[i].minor) || | ||
339 | (id->major != tegra_chip_revisions[i].major) || | ||
340 | (prime != tegra_chip_revisions[i].prime)) | ||
341 | continue; | ||
342 | |||
343 | revision = tegra_chip_revisions[i].revision; | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | #elif defined(CONFIG_TEGRA_FPGA_PLATFORM) | ||
348 | if ((id->chipid & 0xf0) == TEGRA_CHIPID_TEGRA3) { | ||
349 | if ((id->major == 0) && (id->minor == 1)) { | ||
350 | unsigned int patch = id->patch & 0xF; | ||
351 | if ((id->netlist == 12) && (patch == 12)) | ||
352 | revision = TEGRA_REVISION_A01; | ||
353 | else if ((id->netlist == 12) && (patch > 12)) | ||
354 | revision = TEGRA_REVISION_A02; | ||
355 | else if (id->netlist > 12) | ||
356 | revision = TEGRA_REVISION_A02; | ||
357 | } | ||
358 | } | ||
359 | #endif | ||
360 | |||
361 | return revision; | ||
362 | } | ||
363 | |||
364 | static void tegra_set_tegraid(u32 chipid, | ||
365 | u32 major, u32 minor, | ||
366 | u32 nlist, u32 patch, const char *priv) | ||
367 | { | ||
368 | tegra_id.chipid = (enum tegra_chipid) chipid; | ||
369 | tegra_id.major = major; | ||
370 | tegra_id.minor = minor; | ||
371 | tegra_id.netlist = nlist; | ||
372 | tegra_id.patch = patch; | ||
373 | tegra_id.priv = (char *)priv; | ||
374 | tegra_id.revision = tegra_decode_revision(&tegra_id); | ||
375 | } | ||
376 | |||
377 | static void tegra_get_tegraid_from_hw(void) | ||
71 | { | 378 | { |
72 | int cpu_process_id; | 379 | void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804; |
73 | u32 reg = fuse_readl(FUSE_SPARE_BIT); | 380 | void __iomem *netlist = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x860; |
74 | cpu_process_id = (reg >> 6) & 3; | 381 | u32 cid = readl(chip_id); |
75 | return cpu_process_id; | 382 | u32 nlist = readl(netlist); |
383 | char *priv = NULL; | ||
384 | |||
385 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
386 | if (get_spare_fuse(18) || get_spare_fuse(19)) | ||
387 | priv = "p"; | ||
388 | #endif | ||
389 | tegra_set_tegraid((cid >> 8) & 0xff, | ||
390 | (cid >> 4) & 0xf, | ||
391 | (cid >> 16) & 0xf, | ||
392 | (nlist >> 0) & 0xffff, | ||
393 | (nlist >> 16) & 0xffff, | ||
394 | priv); | ||
76 | } | 395 | } |
77 | 396 | ||
78 | int tegra_core_process_id(void) | 397 | enum tegra_chipid tegra_get_chipid(void) |
79 | { | 398 | { |
80 | int core_process_id; | 399 | if (tegra_id.chipid == TEGRA_CHIPID_UNKNOWN) { |
81 | u32 reg = fuse_readl(FUSE_SPARE_BIT); | 400 | /* Boot loader did not pass a valid chip ID. |
82 | core_process_id = (reg >> 12) & 3; | 401 | * Get it from hardware */ |
83 | return core_process_id; | 402 | tegra_get_tegraid_from_hw(); |
403 | } | ||
404 | |||
405 | return tegra_id.chipid; | ||
84 | } | 406 | } |
407 | |||
408 | enum tegra_revision tegra_get_revision(void) | ||
409 | { | ||
410 | if (tegra_id.chipid == TEGRA_CHIPID_UNKNOWN) { | ||
411 | /* Boot loader did not pass a valid chip ID. | ||
412 | * Get it from hardware */ | ||
413 | tegra_get_tegraid_from_hw(); | ||
414 | } | ||
415 | |||
416 | return tegra_id.revision; | ||
417 | } | ||
418 | |||
419 | static char chippriv[16]; /* Permanent buffer for private string */ | ||
420 | static int __init tegra_bootloader_tegraid(char *str) | ||
421 | { | ||
422 | u32 id[5]; | ||
423 | int i = 0; | ||
424 | char *priv = NULL; | ||
425 | |||
426 | do { | ||
427 | id[i++] = simple_strtoul(str, &str, 16); | ||
428 | } while (*str++ && i < ARRAY_SIZE(id)); | ||
429 | |||
430 | if (*(str - 1) == '.') { | ||
431 | strncpy(chippriv, str, sizeof(chippriv) - 1); | ||
432 | priv = chippriv; | ||
433 | if (strlen(str) > sizeof(chippriv) - 1) | ||
434 | pr_err("### tegraid.priv in kernel arg truncated\n"); | ||
435 | } | ||
436 | |||
437 | while (i < ARRAY_SIZE(id)) | ||
438 | id[i++] = 0; | ||
439 | |||
440 | tegra_set_tegraid(id[0], id[1], id[2], id[3], id[4], priv); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static unsigned int get_chip_id(char *val, struct kernel_param *kp) | ||
445 | { | ||
446 | tegra_chip_id = (unsigned int)tegra_get_chipid(); | ||
447 | return param_get_uint(val, kp); | ||
448 | } | ||
449 | static unsigned int get_chip_rev(char *val, struct kernel_param *kp) | ||
450 | { | ||
451 | tegra_chip_rev = (unsigned int)tegra_get_revision(); | ||
452 | return param_get_uint(val, kp); | ||
453 | } | ||
454 | |||
455 | module_param_call(tegra_chip_id, NULL, get_chip_id, &tegra_chip_id, 0444); | ||
456 | __MODULE_PARM_TYPE(tegra_chip_id, "uint"); | ||
457 | module_param_call(tegra_chip_rev, NULL, get_chip_rev, &tegra_chip_rev, 0444); | ||
458 | __MODULE_PARM_TYPE(tegra_chip_rev, "uint"); | ||
459 | |||
460 | /* tegraid=chipid.major.minor.netlist.patch[.priv] */ | ||
461 | early_param("tegraid", tegra_bootloader_tegraid); | ||