GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / soc / tegra / fuse / fuse-tegra30.c
1 /*
2  * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include <linux/device.h>
19 #include <linux/clk.h>
20 #include <linux/err.h>
21 #include <linux/io.h>
22 #include <linux/kernel.h>
23 #include <linux/of_device.h>
24 #include <linux/of_address.h>
25 #include <linux/platform_device.h>
26 #include <linux/random.h>
27
28 #include <soc/tegra/fuse.h>
29
30 #include "fuse.h"
31
32 #define FUSE_BEGIN      0x100
33
34 /* Tegra30 and later */
35 #define FUSE_VENDOR_CODE        0x100
36 #define FUSE_FAB_CODE           0x104
37 #define FUSE_LOT_CODE_0         0x108
38 #define FUSE_LOT_CODE_1         0x10c
39 #define FUSE_WAFER_ID           0x110
40 #define FUSE_X_COORDINATE       0x114
41 #define FUSE_Y_COORDINATE       0x118
42
43 #define FUSE_HAS_REVISION_INFO  BIT(0)
44
45 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
46     defined(CONFIG_ARCH_TEGRA_114_SOC) || \
47     defined(CONFIG_ARCH_TEGRA_124_SOC) || \
48     defined(CONFIG_ARCH_TEGRA_132_SOC) || \
49     defined(CONFIG_ARCH_TEGRA_210_SOC) || \
50     defined(CONFIG_ARCH_TEGRA_186_SOC) || \
51     defined(CONFIG_ARCH_TEGRA_194_SOC) || \
52     defined(CONFIG_ARCH_TEGRA_234_SOC)
53 static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset)
54 {
55         if (WARN_ON(!fuse->base))
56                 return 0;
57
58         return readl_relaxed(fuse->base + FUSE_BEGIN + offset);
59 }
60
61 static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
62 {
63         u32 value;
64         int err;
65
66         err = clk_prepare_enable(fuse->clk);
67         if (err < 0) {
68                 dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err);
69                 return 0;
70         }
71
72         value = readl_relaxed(fuse->base + FUSE_BEGIN + offset);
73
74         clk_disable_unprepare(fuse->clk);
75
76         return value;
77 }
78
79 static void __init tegra30_fuse_add_randomness(void)
80 {
81         u32 randomness[12];
82
83         randomness[0] = tegra_sku_info.sku_id;
84         randomness[1] = tegra_read_straps();
85         randomness[2] = tegra_read_chipid();
86         randomness[3] = tegra_sku_info.cpu_process_id << 16;
87         randomness[3] |= tegra_sku_info.soc_process_id;
88         randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
89         randomness[4] |= tegra_sku_info.soc_speedo_id;
90         randomness[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE);
91         randomness[6] = tegra_fuse_read_early(FUSE_FAB_CODE);
92         randomness[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0);
93         randomness[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1);
94         randomness[9] = tegra_fuse_read_early(FUSE_WAFER_ID);
95         randomness[10] = tegra_fuse_read_early(FUSE_X_COORDINATE);
96         randomness[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE);
97
98         add_device_randomness(randomness, sizeof(randomness));
99 }
100
101 static void __init tegra30_fuse_init(struct tegra_fuse *fuse)
102 {
103         fuse->read_early = tegra30_fuse_read_early;
104         fuse->read = tegra30_fuse_read;
105
106         tegra_init_revision();
107
108         if (fuse->soc->speedo_init)
109                 fuse->soc->speedo_init(&tegra_sku_info);
110
111         tegra30_fuse_add_randomness();
112 }
113 #endif
114
115 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
116 static const struct tegra_fuse_info tegra30_fuse_info = {
117         .read = tegra30_fuse_read,
118         .size = 0x2a4,
119         .spare = 0x144,
120 };
121
122 const struct tegra_fuse_soc tegra30_fuse_soc = {
123         .init = tegra30_fuse_init,
124         .speedo_init = tegra30_init_speedo_data,
125         .info = &tegra30_fuse_info,
126 };
127 #endif
128
129 #ifdef CONFIG_ARCH_TEGRA_114_SOC
130 static const struct tegra_fuse_info tegra114_fuse_info = {
131         .read = tegra30_fuse_read,
132         .size = 0x2a0,
133         .spare = 0x180,
134 };
135
136 const struct tegra_fuse_soc tegra114_fuse_soc = {
137         .init = tegra30_fuse_init,
138         .speedo_init = tegra114_init_speedo_data,
139         .info = &tegra114_fuse_info,
140 };
141 #endif
142
143 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
144 static const struct tegra_fuse_info tegra124_fuse_info = {
145         .read = tegra30_fuse_read,
146         .size = 0x300,
147         .spare = 0x200,
148 };
149
150 const struct tegra_fuse_soc tegra124_fuse_soc = {
151         .init = tegra30_fuse_init,
152         .speedo_init = tegra124_init_speedo_data,
153         .info = &tegra124_fuse_info,
154 };
155 #endif
156
157 #if defined(CONFIG_ARCH_TEGRA_210_SOC)
158 static const struct tegra_fuse_info tegra210_fuse_info = {
159         .read = tegra30_fuse_read,
160         .size = 0x300,
161         .spare = 0x280,
162 };
163
164 const struct tegra_fuse_soc tegra210_fuse_soc = {
165         .init = tegra30_fuse_init,
166         .speedo_init = tegra210_init_speedo_data,
167         .info = &tegra210_fuse_info,
168 };
169 #endif
170
171 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
172 static const struct tegra_fuse_info tegra186_fuse_info = {
173         .read = tegra30_fuse_read,
174         .size = 0x300,
175         .spare = 0x280,
176 };
177
178 const struct tegra_fuse_soc tegra186_fuse_soc = {
179         .init = tegra30_fuse_init,
180         .info = &tegra186_fuse_info,
181 };
182 #endif