1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
6 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/nvmem-consumer.h>
12 #include <linux/of_device.h>
13 #include <linux/of_address.h>
14 #include <linux/platform_device.h>
15 #include <linux/random.h>
17 #include <soc/tegra/fuse.h>
21 #define FUSE_BEGIN 0x100
23 /* Tegra30 and later */
24 #define FUSE_VENDOR_CODE 0x100
25 #define FUSE_FAB_CODE 0x104
26 #define FUSE_LOT_CODE_0 0x108
27 #define FUSE_LOT_CODE_1 0x10c
28 #define FUSE_WAFER_ID 0x110
29 #define FUSE_X_COORDINATE 0x114
30 #define FUSE_Y_COORDINATE 0x118
32 #define FUSE_HAS_REVISION_INFO BIT(0)
34 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
35 defined(CONFIG_ARCH_TEGRA_114_SOC) || \
36 defined(CONFIG_ARCH_TEGRA_124_SOC) || \
37 defined(CONFIG_ARCH_TEGRA_132_SOC) || \
38 defined(CONFIG_ARCH_TEGRA_210_SOC) || \
39 defined(CONFIG_ARCH_TEGRA_186_SOC) || \
40 defined(CONFIG_ARCH_TEGRA_194_SOC)
41 static u32
tegra30_fuse_read_early(struct tegra_fuse
*fuse
, unsigned int offset
)
43 if (WARN_ON(!fuse
->base
))
46 return readl_relaxed(fuse
->base
+ FUSE_BEGIN
+ offset
);
49 static u32
tegra30_fuse_read(struct tegra_fuse
*fuse
, unsigned int offset
)
54 err
= clk_prepare_enable(fuse
->clk
);
56 dev_err(fuse
->dev
, "failed to enable FUSE clock: %d\n", err
);
60 value
= readl_relaxed(fuse
->base
+ FUSE_BEGIN
+ offset
);
62 clk_disable_unprepare(fuse
->clk
);
67 static void __init
tegra30_fuse_add_randomness(void)
71 randomness
[0] = tegra_sku_info
.sku_id
;
72 randomness
[1] = tegra_read_straps();
73 randomness
[2] = tegra_read_chipid();
74 randomness
[3] = tegra_sku_info
.cpu_process_id
<< 16;
75 randomness
[3] |= tegra_sku_info
.soc_process_id
;
76 randomness
[4] = tegra_sku_info
.cpu_speedo_id
<< 16;
77 randomness
[4] |= tegra_sku_info
.soc_speedo_id
;
78 randomness
[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE
);
79 randomness
[6] = tegra_fuse_read_early(FUSE_FAB_CODE
);
80 randomness
[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0
);
81 randomness
[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1
);
82 randomness
[9] = tegra_fuse_read_early(FUSE_WAFER_ID
);
83 randomness
[10] = tegra_fuse_read_early(FUSE_X_COORDINATE
);
84 randomness
[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE
);
86 add_device_randomness(randomness
, sizeof(randomness
));
89 static void __init
tegra30_fuse_init(struct tegra_fuse
*fuse
)
91 fuse
->read_early
= tegra30_fuse_read_early
;
92 fuse
->read
= tegra30_fuse_read
;
94 tegra_init_revision();
96 if (fuse
->soc
->speedo_init
)
97 fuse
->soc
->speedo_init(&tegra_sku_info
);
99 tegra30_fuse_add_randomness();
103 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
104 static const struct tegra_fuse_info tegra30_fuse_info
= {
105 .read
= tegra30_fuse_read
,
110 const struct tegra_fuse_soc tegra30_fuse_soc
= {
111 .init
= tegra30_fuse_init
,
112 .speedo_init
= tegra30_init_speedo_data
,
113 .info
= &tegra30_fuse_info
,
114 .soc_attr_group
= &tegra_soc_attr_group
,
118 #ifdef CONFIG_ARCH_TEGRA_114_SOC
119 static const struct tegra_fuse_info tegra114_fuse_info
= {
120 .read
= tegra30_fuse_read
,
125 const struct tegra_fuse_soc tegra114_fuse_soc
= {
126 .init
= tegra30_fuse_init
,
127 .speedo_init
= tegra114_init_speedo_data
,
128 .info
= &tegra114_fuse_info
,
129 .soc_attr_group
= &tegra_soc_attr_group
,
133 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
134 static const struct nvmem_cell_lookup tegra124_fuse_lookups
[] = {
136 .nvmem_name
= "fuse",
137 .cell_name
= "xusb-pad-calibration",
138 .dev_id
= "7009f000.padctl",
139 .con_id
= "calibration",
141 .nvmem_name
= "fuse",
142 .cell_name
= "sata-calibration",
143 .dev_id
= "70020000.sata",
144 .con_id
= "calibration",
146 .nvmem_name
= "fuse",
147 .cell_name
= "tsensor-common",
148 .dev_id
= "700e2000.thermal-sensor",
151 .nvmem_name
= "fuse",
152 .cell_name
= "tsensor-realignment",
153 .dev_id
= "700e2000.thermal-sensor",
154 .con_id
= "realignment",
156 .nvmem_name
= "fuse",
157 .cell_name
= "tsensor-cpu0",
158 .dev_id
= "700e2000.thermal-sensor",
161 .nvmem_name
= "fuse",
162 .cell_name
= "tsensor-cpu1",
163 .dev_id
= "700e2000.thermal-sensor",
166 .nvmem_name
= "fuse",
167 .cell_name
= "tsensor-cpu2",
168 .dev_id
= "700e2000.thermal-sensor",
171 .nvmem_name
= "fuse",
172 .cell_name
= "tsensor-cpu3",
173 .dev_id
= "700e2000.thermal-sensor",
176 .nvmem_name
= "fuse",
177 .cell_name
= "tsensor-mem0",
178 .dev_id
= "700e2000.thermal-sensor",
181 .nvmem_name
= "fuse",
182 .cell_name
= "tsensor-mem1",
183 .dev_id
= "700e2000.thermal-sensor",
186 .nvmem_name
= "fuse",
187 .cell_name
= "tsensor-gpu",
188 .dev_id
= "700e2000.thermal-sensor",
191 .nvmem_name
= "fuse",
192 .cell_name
= "tsensor-pllx",
193 .dev_id
= "700e2000.thermal-sensor",
198 static const struct tegra_fuse_info tegra124_fuse_info
= {
199 .read
= tegra30_fuse_read
,
204 const struct tegra_fuse_soc tegra124_fuse_soc
= {
205 .init
= tegra30_fuse_init
,
206 .speedo_init
= tegra124_init_speedo_data
,
207 .info
= &tegra124_fuse_info
,
208 .lookups
= tegra124_fuse_lookups
,
209 .num_lookups
= ARRAY_SIZE(tegra124_fuse_lookups
),
210 .soc_attr_group
= &tegra_soc_attr_group
,
214 #if defined(CONFIG_ARCH_TEGRA_210_SOC)
215 static const struct nvmem_cell_lookup tegra210_fuse_lookups
[] = {
217 .nvmem_name
= "fuse",
218 .cell_name
= "tsensor-cpu1",
219 .dev_id
= "700e2000.thermal-sensor",
222 .nvmem_name
= "fuse",
223 .cell_name
= "tsensor-cpu2",
224 .dev_id
= "700e2000.thermal-sensor",
227 .nvmem_name
= "fuse",
228 .cell_name
= "tsensor-cpu0",
229 .dev_id
= "700e2000.thermal-sensor",
232 .nvmem_name
= "fuse",
233 .cell_name
= "xusb-pad-calibration",
234 .dev_id
= "7009f000.padctl",
235 .con_id
= "calibration",
237 .nvmem_name
= "fuse",
238 .cell_name
= "tsensor-cpu3",
239 .dev_id
= "700e2000.thermal-sensor",
242 .nvmem_name
= "fuse",
243 .cell_name
= "sata-calibration",
244 .dev_id
= "70020000.sata",
245 .con_id
= "calibration",
247 .nvmem_name
= "fuse",
248 .cell_name
= "tsensor-gpu",
249 .dev_id
= "700e2000.thermal-sensor",
252 .nvmem_name
= "fuse",
253 .cell_name
= "tsensor-mem0",
254 .dev_id
= "700e2000.thermal-sensor",
257 .nvmem_name
= "fuse",
258 .cell_name
= "tsensor-mem1",
259 .dev_id
= "700e2000.thermal-sensor",
262 .nvmem_name
= "fuse",
263 .cell_name
= "tsensor-pllx",
264 .dev_id
= "700e2000.thermal-sensor",
267 .nvmem_name
= "fuse",
268 .cell_name
= "tsensor-common",
269 .dev_id
= "700e2000.thermal-sensor",
272 .nvmem_name
= "fuse",
273 .cell_name
= "gpu-calibration",
274 .dev_id
= "57000000.gpu",
275 .con_id
= "calibration",
277 .nvmem_name
= "fuse",
278 .cell_name
= "xusb-pad-calibration-ext",
279 .dev_id
= "7009f000.padctl",
280 .con_id
= "calibration-ext",
284 static const struct tegra_fuse_info tegra210_fuse_info
= {
285 .read
= tegra30_fuse_read
,
290 const struct tegra_fuse_soc tegra210_fuse_soc
= {
291 .init
= tegra30_fuse_init
,
292 .speedo_init
= tegra210_init_speedo_data
,
293 .info
= &tegra210_fuse_info
,
294 .lookups
= tegra210_fuse_lookups
,
295 .num_lookups
= ARRAY_SIZE(tegra210_fuse_lookups
),
296 .soc_attr_group
= &tegra_soc_attr_group
,
300 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
301 static const struct nvmem_cell_lookup tegra186_fuse_lookups
[] = {
303 .nvmem_name
= "fuse",
304 .cell_name
= "xusb-pad-calibration",
305 .dev_id
= "3520000.padctl",
306 .con_id
= "calibration",
308 .nvmem_name
= "fuse",
309 .cell_name
= "xusb-pad-calibration-ext",
310 .dev_id
= "3520000.padctl",
311 .con_id
= "calibration-ext",
315 static const struct tegra_fuse_info tegra186_fuse_info
= {
316 .read
= tegra30_fuse_read
,
321 const struct tegra_fuse_soc tegra186_fuse_soc
= {
322 .init
= tegra30_fuse_init
,
323 .info
= &tegra186_fuse_info
,
324 .lookups
= tegra186_fuse_lookups
,
325 .num_lookups
= ARRAY_SIZE(tegra186_fuse_lookups
),
326 .soc_attr_group
= &tegra_soc_attr_group
,
330 #if defined(CONFIG_ARCH_TEGRA_194_SOC)
331 static const struct nvmem_cell_lookup tegra194_fuse_lookups
[] = {
333 .nvmem_name
= "fuse",
334 .cell_name
= "xusb-pad-calibration",
335 .dev_id
= "3520000.padctl",
336 .con_id
= "calibration",
338 .nvmem_name
= "fuse",
339 .cell_name
= "xusb-pad-calibration-ext",
340 .dev_id
= "3520000.padctl",
341 .con_id
= "calibration-ext",
345 static const struct tegra_fuse_info tegra194_fuse_info
= {
346 .read
= tegra30_fuse_read
,
351 const struct tegra_fuse_soc tegra194_fuse_soc
= {
352 .init
= tegra30_fuse_init
,
353 .info
= &tegra194_fuse_info
,
354 .lookups
= tegra194_fuse_lookups
,
355 .num_lookups
= ARRAY_SIZE(tegra194_fuse_lookups
),
356 .soc_attr_group
= &tegra194_soc_attr_group
,
360 #if defined(CONFIG_ARCH_TEGRA_234_SOC)
361 static const struct nvmem_cell_lookup tegra234_fuse_lookups
[] = {
363 .nvmem_name
= "fuse",
364 .cell_name
= "xusb-pad-calibration",
365 .dev_id
= "3520000.padctl",
366 .con_id
= "calibration",
368 .nvmem_name
= "fuse",
369 .cell_name
= "xusb-pad-calibration-ext",
370 .dev_id
= "3520000.padctl",
371 .con_id
= "calibration-ext",
375 static const struct tegra_fuse_info tegra234_fuse_info
= {
376 .read
= tegra30_fuse_read
,
381 const struct tegra_fuse_soc tegra234_fuse_soc
= {
382 .init
= tegra30_fuse_init
,
383 .info
= &tegra234_fuse_info
,
384 .lookups
= tegra234_fuse_lookups
,
385 .num_lookups
= ARRAY_SIZE(tegra234_fuse_lookups
),
386 .soc_attr_group
= &tegra194_soc_attr_group
,