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 defined(CONFIG_ARCH_TEGRA_194_SOC)
40 static u32
tegra30_fuse_read_early(struct tegra_fuse
*fuse
, unsigned int offset
)
42 if (WARN_ON(!fuse
->base
))
45 return readl_relaxed(fuse
->base
+ FUSE_BEGIN
+ offset
);
48 static u32
tegra30_fuse_read(struct tegra_fuse
*fuse
, unsigned int offset
)
53 err
= clk_prepare_enable(fuse
->clk
);
55 dev_err(fuse
->dev
, "failed to enable FUSE clock: %d\n", err
);
59 value
= readl_relaxed(fuse
->base
+ FUSE_BEGIN
+ offset
);
61 clk_disable_unprepare(fuse
->clk
);
66 static void __init
tegra30_fuse_add_randomness(void)
70 randomness
[0] = tegra_sku_info
.sku_id
;
71 randomness
[1] = tegra_read_straps();
72 randomness
[2] = tegra_read_chipid();
73 randomness
[3] = tegra_sku_info
.cpu_process_id
<< 16;
74 randomness
[3] |= tegra_sku_info
.soc_process_id
;
75 randomness
[4] = tegra_sku_info
.cpu_speedo_id
<< 16;
76 randomness
[4] |= tegra_sku_info
.soc_speedo_id
;
77 randomness
[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE
);
78 randomness
[6] = tegra_fuse_read_early(FUSE_FAB_CODE
);
79 randomness
[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0
);
80 randomness
[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1
);
81 randomness
[9] = tegra_fuse_read_early(FUSE_WAFER_ID
);
82 randomness
[10] = tegra_fuse_read_early(FUSE_X_COORDINATE
);
83 randomness
[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE
);
85 add_device_randomness(randomness
, sizeof(randomness
));
88 static void __init
tegra30_fuse_init(struct tegra_fuse
*fuse
)
90 fuse
->read_early
= tegra30_fuse_read_early
;
91 fuse
->read
= tegra30_fuse_read
;
93 tegra_init_revision();
95 if (fuse
->soc
->speedo_init
)
96 fuse
->soc
->speedo_init(&tegra_sku_info
);
98 tegra30_fuse_add_randomness();
102 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
103 static const struct tegra_fuse_info tegra30_fuse_info
= {
104 .read
= tegra30_fuse_read
,
109 const struct tegra_fuse_soc tegra30_fuse_soc
= {
110 .init
= tegra30_fuse_init
,
111 .speedo_init
= tegra30_init_speedo_data
,
112 .info
= &tegra30_fuse_info
,
116 #ifdef CONFIG_ARCH_TEGRA_114_SOC
117 static const struct tegra_fuse_info tegra114_fuse_info
= {
118 .read
= tegra30_fuse_read
,
123 const struct tegra_fuse_soc tegra114_fuse_soc
= {
124 .init
= tegra30_fuse_init
,
125 .speedo_init
= tegra114_init_speedo_data
,
126 .info
= &tegra114_fuse_info
,
130 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
131 static const struct tegra_fuse_info tegra124_fuse_info
= {
132 .read
= tegra30_fuse_read
,
137 const struct tegra_fuse_soc tegra124_fuse_soc
= {
138 .init
= tegra30_fuse_init
,
139 .speedo_init
= tegra124_init_speedo_data
,
140 .info
= &tegra124_fuse_info
,
144 #if defined(CONFIG_ARCH_TEGRA_210_SOC)
145 static const struct tegra_fuse_info tegra210_fuse_info
= {
146 .read
= tegra30_fuse_read
,
151 const struct tegra_fuse_soc tegra210_fuse_soc
= {
152 .init
= tegra30_fuse_init
,
153 .speedo_init
= tegra210_init_speedo_data
,
154 .info
= &tegra210_fuse_info
,
158 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
159 static const struct tegra_fuse_info tegra186_fuse_info
= {
160 .read
= tegra30_fuse_read
,
165 const struct tegra_fuse_soc tegra186_fuse_soc
= {
166 .init
= tegra30_fuse_init
,
167 .info
= &tegra186_fuse_info
,