treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 201
[linux-block.git] / drivers / soc / tegra / fuse / fuse-tegra.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
4  */
5
6 #include <linux/clk.h>
7 #include <linux/device.h>
8 #include <linux/kobject.h>
9 #include <linux/init.h>
10 #include <linux/io.h>
11 #include <linux/of.h>
12 #include <linux/of_address.h>
13 #include <linux/platform_device.h>
14 #include <linux/slab.h>
15 #include <linux/sys_soc.h>
16
17 #include <soc/tegra/common.h>
18 #include <soc/tegra/fuse.h>
19
20 #include "fuse.h"
21
22 struct tegra_sku_info tegra_sku_info;
23 EXPORT_SYMBOL(tegra_sku_info);
24
25 static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
26         [TEGRA_REVISION_UNKNOWN] = "unknown",
27         [TEGRA_REVISION_A01]     = "A01",
28         [TEGRA_REVISION_A02]     = "A02",
29         [TEGRA_REVISION_A03]     = "A03",
30         [TEGRA_REVISION_A03p]    = "A03 prime",
31         [TEGRA_REVISION_A04]     = "A04",
32 };
33
34 static u8 fuse_readb(struct tegra_fuse *fuse, unsigned int offset)
35 {
36         u32 val;
37
38         val = fuse->read(fuse, round_down(offset, 4));
39         val >>= (offset % 4) * 8;
40         val &= 0xff;
41
42         return val;
43 }
44
45 static ssize_t fuse_read(struct file *fd, struct kobject *kobj,
46                          struct bin_attribute *attr, char *buf,
47                          loff_t pos, size_t size)
48 {
49         struct device *dev = kobj_to_dev(kobj);
50         struct tegra_fuse *fuse = dev_get_drvdata(dev);
51         int i;
52
53         if (pos < 0 || pos >= attr->size)
54                 return 0;
55
56         if (size > attr->size - pos)
57                 size = attr->size - pos;
58
59         for (i = 0; i < size; i++)
60                 buf[i] = fuse_readb(fuse, pos + i);
61
62         return i;
63 }
64
65 static struct bin_attribute fuse_bin_attr = {
66         .attr = { .name = "fuse", .mode = S_IRUGO, },
67         .read = fuse_read,
68 };
69
70 static int tegra_fuse_create_sysfs(struct device *dev, unsigned int size,
71                                    const struct tegra_fuse_info *info)
72 {
73         fuse_bin_attr.size = size;
74
75         return device_create_bin_file(dev, &fuse_bin_attr);
76 }
77
78 static const struct of_device_id car_match[] __initconst = {
79         { .compatible = "nvidia,tegra20-car", },
80         { .compatible = "nvidia,tegra30-car", },
81         { .compatible = "nvidia,tegra114-car", },
82         { .compatible = "nvidia,tegra124-car", },
83         { .compatible = "nvidia,tegra132-car", },
84         { .compatible = "nvidia,tegra210-car", },
85         {},
86 };
87
88 static struct tegra_fuse *fuse = &(struct tegra_fuse) {
89         .base = NULL,
90         .soc = NULL,
91 };
92
93 static const struct of_device_id tegra_fuse_match[] = {
94 #ifdef CONFIG_ARCH_TEGRA_186_SOC
95         { .compatible = "nvidia,tegra186-efuse", .data = &tegra186_fuse_soc },
96 #endif
97 #ifdef CONFIG_ARCH_TEGRA_210_SOC
98         { .compatible = "nvidia,tegra210-efuse", .data = &tegra210_fuse_soc },
99 #endif
100 #ifdef CONFIG_ARCH_TEGRA_132_SOC
101         { .compatible = "nvidia,tegra132-efuse", .data = &tegra124_fuse_soc },
102 #endif
103 #ifdef CONFIG_ARCH_TEGRA_124_SOC
104         { .compatible = "nvidia,tegra124-efuse", .data = &tegra124_fuse_soc },
105 #endif
106 #ifdef CONFIG_ARCH_TEGRA_114_SOC
107         { .compatible = "nvidia,tegra114-efuse", .data = &tegra114_fuse_soc },
108 #endif
109 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
110         { .compatible = "nvidia,tegra30-efuse", .data = &tegra30_fuse_soc },
111 #endif
112 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
113         { .compatible = "nvidia,tegra20-efuse", .data = &tegra20_fuse_soc },
114 #endif
115         { /* sentinel */ }
116 };
117
118 static int tegra_fuse_probe(struct platform_device *pdev)
119 {
120         void __iomem *base = fuse->base;
121         struct resource *res;
122         int err;
123
124         /* take over the memory region from the early initialization */
125         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
126         fuse->phys = res->start;
127         fuse->base = devm_ioremap_resource(&pdev->dev, res);
128         if (IS_ERR(fuse->base)) {
129                 err = PTR_ERR(fuse->base);
130                 fuse->base = base;
131                 return err;
132         }
133
134         fuse->clk = devm_clk_get(&pdev->dev, "fuse");
135         if (IS_ERR(fuse->clk)) {
136                 dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
137                         PTR_ERR(fuse->clk));
138                 fuse->base = base;
139                 return PTR_ERR(fuse->clk);
140         }
141
142         platform_set_drvdata(pdev, fuse);
143         fuse->dev = &pdev->dev;
144
145         if (fuse->soc->probe) {
146                 err = fuse->soc->probe(fuse);
147                 if (err < 0) {
148                         fuse->base = base;
149                         return err;
150                 }
151         }
152
153         if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size,
154                                     fuse->soc->info))
155                 return -ENODEV;
156
157         /* release the early I/O memory mapping */
158         iounmap(base);
159
160         return 0;
161 }
162
163 static struct platform_driver tegra_fuse_driver = {
164         .driver = {
165                 .name = "tegra-fuse",
166                 .of_match_table = tegra_fuse_match,
167                 .suppress_bind_attrs = true,
168         },
169         .probe = tegra_fuse_probe,
170 };
171 builtin_platform_driver(tegra_fuse_driver);
172
173 bool __init tegra_fuse_read_spare(unsigned int spare)
174 {
175         unsigned int offset = fuse->soc->info->spare + spare * 4;
176
177         return fuse->read_early(fuse, offset) & 1;
178 }
179
180 u32 __init tegra_fuse_read_early(unsigned int offset)
181 {
182         return fuse->read_early(fuse, offset);
183 }
184
185 int tegra_fuse_readl(unsigned long offset, u32 *value)
186 {
187         if (!fuse->read)
188                 return -EPROBE_DEFER;
189
190         *value = fuse->read(fuse, offset);
191
192         return 0;
193 }
194 EXPORT_SYMBOL(tegra_fuse_readl);
195
196 static void tegra_enable_fuse_clk(void __iomem *base)
197 {
198         u32 reg;
199
200         reg = readl_relaxed(base + 0x48);
201         reg |= 1 << 28;
202         writel(reg, base + 0x48);
203
204         /*
205          * Enable FUSE clock. This needs to be hardcoded because the clock
206          * subsystem is not active during early boot.
207          */
208         reg = readl(base + 0x14);
209         reg |= 1 << 7;
210         writel(reg, base + 0x14);
211 }
212
213 struct device * __init tegra_soc_device_register(void)
214 {
215         struct soc_device_attribute *attr;
216         struct soc_device *dev;
217
218         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
219         if (!attr)
220                 return NULL;
221
222         attr->family = kasprintf(GFP_KERNEL, "Tegra");
223         attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_sku_info.revision);
224         attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id());
225
226         dev = soc_device_register(attr);
227         if (IS_ERR(dev)) {
228                 kfree(attr->soc_id);
229                 kfree(attr->revision);
230                 kfree(attr->family);
231                 kfree(attr);
232                 return ERR_CAST(dev);
233         }
234
235         return soc_device_to_device(dev);
236 }
237
238 static int __init tegra_init_fuse(void)
239 {
240         const struct of_device_id *match;
241         struct device_node *np;
242         struct resource regs;
243
244         tegra_init_apbmisc();
245
246         np = of_find_matching_node_and_match(NULL, tegra_fuse_match, &match);
247         if (!np) {
248                 /*
249                  * Fall back to legacy initialization for 32-bit ARM only. All
250                  * 64-bit ARM device tree files for Tegra are required to have
251                  * a FUSE node.
252                  *
253                  * This is for backwards-compatibility with old device trees
254                  * that didn't contain a FUSE node.
255                  */
256                 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
257                         u8 chip = tegra_get_chip_id();
258
259                         regs.start = 0x7000f800;
260                         regs.end = 0x7000fbff;
261                         regs.flags = IORESOURCE_MEM;
262
263                         switch (chip) {
264 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
265                         case TEGRA20:
266                                 fuse->soc = &tegra20_fuse_soc;
267                                 break;
268 #endif
269
270 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
271                         case TEGRA30:
272                                 fuse->soc = &tegra30_fuse_soc;
273                                 break;
274 #endif
275
276 #ifdef CONFIG_ARCH_TEGRA_114_SOC
277                         case TEGRA114:
278                                 fuse->soc = &tegra114_fuse_soc;
279                                 break;
280 #endif
281
282 #ifdef CONFIG_ARCH_TEGRA_124_SOC
283                         case TEGRA124:
284                                 fuse->soc = &tegra124_fuse_soc;
285                                 break;
286 #endif
287
288                         default:
289                                 pr_warn("Unsupported SoC: %02x\n", chip);
290                                 break;
291                         }
292                 } else {
293                         /*
294                          * At this point we're not running on Tegra, so play
295                          * nice with multi-platform kernels.
296                          */
297                         return 0;
298                 }
299         } else {
300                 /*
301                  * Extract information from the device tree if we've found a
302                  * matching node.
303                  */
304                 if (of_address_to_resource(np, 0, &regs) < 0) {
305                         pr_err("failed to get FUSE register\n");
306                         return -ENXIO;
307                 }
308
309                 fuse->soc = match->data;
310         }
311
312         np = of_find_matching_node(NULL, car_match);
313         if (np) {
314                 void __iomem *base = of_iomap(np, 0);
315                 if (base) {
316                         tegra_enable_fuse_clk(base);
317                         iounmap(base);
318                 } else {
319                         pr_err("failed to map clock registers\n");
320                         return -ENXIO;
321                 }
322         }
323
324         fuse->base = ioremap_nocache(regs.start, resource_size(&regs));
325         if (!fuse->base) {
326                 pr_err("failed to map FUSE registers\n");
327                 return -ENXIO;
328         }
329
330         fuse->soc->init(fuse);
331
332         pr_info("Tegra Revision: %s SKU: %d CPU Process: %d SoC Process: %d\n",
333                 tegra_revision_name[tegra_sku_info.revision],
334                 tegra_sku_info.sku_id, tegra_sku_info.cpu_process_id,
335                 tegra_sku_info.soc_process_id);
336         pr_debug("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n",
337                  tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);
338
339
340         return 0;
341 }
342 early_initcall(tegra_init_fuse);
343
344 #ifdef CONFIG_ARM64
345 static int __init tegra_init_soc(void)
346 {
347         struct device_node *np;
348         struct device *soc;
349
350         /* make sure we're running on Tegra */
351         np = of_find_matching_node(NULL, tegra_fuse_match);
352         if (!np)
353                 return 0;
354
355         of_node_put(np);
356
357         soc = tegra_soc_device_register();
358         if (IS_ERR(soc)) {
359                 pr_err("failed to register SoC device: %ld\n", PTR_ERR(soc));
360                 return PTR_ERR(soc);
361         }
362
363         return 0;
364 }
365 device_initcall(tegra_init_soc);
366 #endif