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/of_device.h>
12 #include <linux/of_address.h>
13 #include <linux/platform_device.h>
14 #include <linux/random.h>
16 #include <soc/tegra/fuse.h>
20 #define FUSE_BEGIN 0x100
22 /* Tegra30 and later */
23 #define FUSE_VENDOR_CODE 0x100
24 #define FUSE_FAB_CODE 0x104
25 #define FUSE_LOT_CODE_0 0x108
26 #define FUSE_LOT_CODE_1 0x10c
27 #define FUSE_WAFER_ID 0x110
28 #define FUSE_X_COORDINATE 0x114
29 #define FUSE_Y_COORDINATE 0x118
31 #define FUSE_HAS_REVISION_INFO BIT(0)
33 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
34 defined(CONFIG_ARCH_TEGRA_114_SOC) || \
35 defined(CONFIG_ARCH_TEGRA_124_SOC) || \
36 defined(CONFIG_ARCH_TEGRA_132_SOC) || \
37 defined(CONFIG_ARCH_TEGRA_210_SOC) || \
38 defined(CONFIG_ARCH_TEGRA_186_SOC)
39 static u32
tegra30_fuse_read_early(struct tegra_fuse
*fuse
, unsigned int offset
)
41 if (WARN_ON(!fuse
->base
))
44 return readl_relaxed(fuse
->base
+ FUSE_BEGIN
+ offset
);
47 static u32
tegra30_fuse_read(struct tegra_fuse
*fuse
, unsigned int offset
)
52 err
= clk_prepare_enable(fuse
->clk
);
54 dev_err(fuse
->dev
, "failed to enable FUSE clock: %d\n", err
);
58 value
= readl_relaxed(fuse
->base
+ FUSE_BEGIN
+ offset
);
60 clk_disable_unprepare(fuse
->clk
);
65 static void __init
tegra30_fuse_add_randomness(void)
69 randomness
[0] = tegra_sku_info
.sku_id
;
70 randomness
[1] = tegra_read_straps();
71 randomness
[2] = tegra_read_chipid();
72 randomness
[3] = tegra_sku_info
.cpu_process_id
<< 16;
73 randomness
[3] |= tegra_sku_info
.soc_process_id
;
74 randomness
[4] = tegra_sku_info
.cpu_speedo_id
<< 16;
75 randomness
[4] |= tegra_sku_info
.soc_speedo_id
;
76 randomness
[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE
);
77 randomness
[6] = tegra_fuse_read_early(FUSE_FAB_CODE
);
78 randomness
[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0
);
79 randomness
[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1
);
80 randomness
[9] = tegra_fuse_read_early(FUSE_WAFER_ID
);
81 randomness
[10] = tegra_fuse_read_early(FUSE_X_COORDINATE
);
82 randomness
[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE
);
84 add_device_randomness(randomness
, sizeof(randomness
));
87 static void __init
tegra30_fuse_init(struct tegra_fuse
*fuse
)
89 fuse
->read_early
= tegra30_fuse_read_early
;
90 fuse
->read
= tegra30_fuse_read
;
92 tegra_init_revision();
94 if (fuse
->soc
->speedo_init
)
95 fuse
->soc
->speedo_init(&tegra_sku_info
);
97 tegra30_fuse_add_randomness();
101 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
102 static const struct tegra_fuse_info tegra30_fuse_info
= {
103 .read
= tegra30_fuse_read
,
108 const struct tegra_fuse_soc tegra30_fuse_soc
= {
109 .init
= tegra30_fuse_init
,
110 .speedo_init
= tegra30_init_speedo_data
,
111 .info
= &tegra30_fuse_info
,
115 #ifdef CONFIG_ARCH_TEGRA_114_SOC
116 static const struct tegra_fuse_info tegra114_fuse_info
= {
117 .read
= tegra30_fuse_read
,
122 const struct tegra_fuse_soc tegra114_fuse_soc
= {
123 .init
= tegra30_fuse_init
,
124 .speedo_init
= tegra114_init_speedo_data
,
125 .info
= &tegra114_fuse_info
,
129 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
130 static const struct tegra_fuse_info tegra124_fuse_info
= {
131 .read
= tegra30_fuse_read
,
136 const struct tegra_fuse_soc tegra124_fuse_soc
= {
137 .init
= tegra30_fuse_init
,
138 .speedo_init
= tegra124_init_speedo_data
,
139 .info
= &tegra124_fuse_info
,
143 #if defined(CONFIG_ARCH_TEGRA_210_SOC)
144 static const struct tegra_fuse_info tegra210_fuse_info
= {
145 .read
= tegra30_fuse_read
,
150 const struct tegra_fuse_soc tegra210_fuse_soc
= {
151 .init
= tegra30_fuse_init
,
152 .speedo_init
= tegra210_init_speedo_data
,
153 .info
= &tegra210_fuse_info
,
157 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
158 static const struct tegra_fuse_info tegra186_fuse_info
= {
159 .read
= tegra30_fuse_read
,
164 const struct tegra_fuse_soc tegra186_fuse_soc
= {
165 .init
= tegra30_fuse_init
,
166 .info
= &tegra186_fuse_info
,