Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2013-2022, NVIDIA CORPORATION.  All rights reserved.
0004  */
0005 
0006 #include <linux/device.h>
0007 #include <linux/clk.h>
0008 #include <linux/err.h>
0009 #include <linux/io.h>
0010 #include <linux/kernel.h>
0011 #include <linux/nvmem-consumer.h>
0012 #include <linux/of_device.h>
0013 #include <linux/of_address.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/random.h>
0017 
0018 #include <soc/tegra/fuse.h>
0019 
0020 #include "fuse.h"
0021 
0022 #define FUSE_BEGIN  0x100
0023 
0024 /* Tegra30 and later */
0025 #define FUSE_VENDOR_CODE    0x100
0026 #define FUSE_FAB_CODE       0x104
0027 #define FUSE_LOT_CODE_0     0x108
0028 #define FUSE_LOT_CODE_1     0x10c
0029 #define FUSE_WAFER_ID       0x110
0030 #define FUSE_X_COORDINATE   0x114
0031 #define FUSE_Y_COORDINATE   0x118
0032 
0033 #define FUSE_HAS_REVISION_INFO  BIT(0)
0034 
0035 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
0036     defined(CONFIG_ARCH_TEGRA_114_SOC) || \
0037     defined(CONFIG_ARCH_TEGRA_124_SOC) || \
0038     defined(CONFIG_ARCH_TEGRA_132_SOC) || \
0039     defined(CONFIG_ARCH_TEGRA_210_SOC) || \
0040     defined(CONFIG_ARCH_TEGRA_186_SOC) || \
0041     defined(CONFIG_ARCH_TEGRA_194_SOC) || \
0042     defined(CONFIG_ARCH_TEGRA_234_SOC)
0043 static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset)
0044 {
0045     if (WARN_ON(!fuse->base))
0046         return 0;
0047 
0048     return readl_relaxed(fuse->base + FUSE_BEGIN + offset);
0049 }
0050 
0051 static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
0052 {
0053     u32 value;
0054     int err;
0055 
0056     err = pm_runtime_resume_and_get(fuse->dev);
0057     if (err)
0058         return 0;
0059 
0060     value = readl_relaxed(fuse->base + FUSE_BEGIN + offset);
0061 
0062     pm_runtime_put(fuse->dev);
0063 
0064     return value;
0065 }
0066 
0067 static void __init tegra30_fuse_add_randomness(void)
0068 {
0069     u32 randomness[12];
0070 
0071     randomness[0] = tegra_sku_info.sku_id;
0072     randomness[1] = tegra_read_straps();
0073     randomness[2] = tegra_read_chipid();
0074     randomness[3] = tegra_sku_info.cpu_process_id << 16;
0075     randomness[3] |= tegra_sku_info.soc_process_id;
0076     randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
0077     randomness[4] |= tegra_sku_info.soc_speedo_id;
0078     randomness[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE);
0079     randomness[6] = tegra_fuse_read_early(FUSE_FAB_CODE);
0080     randomness[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0);
0081     randomness[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1);
0082     randomness[9] = tegra_fuse_read_early(FUSE_WAFER_ID);
0083     randomness[10] = tegra_fuse_read_early(FUSE_X_COORDINATE);
0084     randomness[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE);
0085 
0086     add_device_randomness(randomness, sizeof(randomness));
0087 }
0088 
0089 static void __init tegra30_fuse_init(struct tegra_fuse *fuse)
0090 {
0091     fuse->read_early = tegra30_fuse_read_early;
0092     fuse->read = tegra30_fuse_read;
0093 
0094     tegra_init_revision();
0095 
0096     if (fuse->soc->speedo_init)
0097         fuse->soc->speedo_init(&tegra_sku_info);
0098 
0099     tegra30_fuse_add_randomness();
0100 }
0101 #endif
0102 
0103 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
0104 static const struct tegra_fuse_info tegra30_fuse_info = {
0105     .read = tegra30_fuse_read,
0106     .size = 0x2a4,
0107     .spare = 0x144,
0108 };
0109 
0110 const struct tegra_fuse_soc tegra30_fuse_soc = {
0111     .init = tegra30_fuse_init,
0112     .speedo_init = tegra30_init_speedo_data,
0113     .info = &tegra30_fuse_info,
0114     .soc_attr_group = &tegra_soc_attr_group,
0115     .clk_suspend_on = false,
0116 };
0117 #endif
0118 
0119 #ifdef CONFIG_ARCH_TEGRA_114_SOC
0120 static const struct tegra_fuse_info tegra114_fuse_info = {
0121     .read = tegra30_fuse_read,
0122     .size = 0x2a0,
0123     .spare = 0x180,
0124 };
0125 
0126 const struct tegra_fuse_soc tegra114_fuse_soc = {
0127     .init = tegra30_fuse_init,
0128     .speedo_init = tegra114_init_speedo_data,
0129     .info = &tegra114_fuse_info,
0130     .soc_attr_group = &tegra_soc_attr_group,
0131     .clk_suspend_on = false,
0132 };
0133 #endif
0134 
0135 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
0136 static const struct nvmem_cell_lookup tegra124_fuse_lookups[] = {
0137     {
0138         .nvmem_name = "fuse",
0139         .cell_name = "xusb-pad-calibration",
0140         .dev_id = "7009f000.padctl",
0141         .con_id = "calibration",
0142     }, {
0143         .nvmem_name = "fuse",
0144         .cell_name = "sata-calibration",
0145         .dev_id = "70020000.sata",
0146         .con_id = "calibration",
0147     }, {
0148         .nvmem_name = "fuse",
0149         .cell_name = "tsensor-common",
0150         .dev_id = "700e2000.thermal-sensor",
0151         .con_id = "common",
0152     }, {
0153         .nvmem_name = "fuse",
0154         .cell_name = "tsensor-realignment",
0155         .dev_id = "700e2000.thermal-sensor",
0156         .con_id = "realignment",
0157     }, {
0158         .nvmem_name = "fuse",
0159         .cell_name = "tsensor-cpu0",
0160         .dev_id = "700e2000.thermal-sensor",
0161         .con_id = "cpu0",
0162     }, {
0163         .nvmem_name = "fuse",
0164         .cell_name = "tsensor-cpu1",
0165         .dev_id = "700e2000.thermal-sensor",
0166         .con_id = "cpu1",
0167     }, {
0168         .nvmem_name = "fuse",
0169         .cell_name = "tsensor-cpu2",
0170         .dev_id = "700e2000.thermal-sensor",
0171         .con_id = "cpu2",
0172     }, {
0173         .nvmem_name = "fuse",
0174         .cell_name = "tsensor-cpu3",
0175         .dev_id = "700e2000.thermal-sensor",
0176         .con_id = "cpu3",
0177     }, {
0178         .nvmem_name = "fuse",
0179         .cell_name = "tsensor-mem0",
0180         .dev_id = "700e2000.thermal-sensor",
0181         .con_id = "mem0",
0182     }, {
0183         .nvmem_name = "fuse",
0184         .cell_name = "tsensor-mem1",
0185         .dev_id = "700e2000.thermal-sensor",
0186         .con_id = "mem1",
0187     }, {
0188         .nvmem_name = "fuse",
0189         .cell_name = "tsensor-gpu",
0190         .dev_id = "700e2000.thermal-sensor",
0191         .con_id = "gpu",
0192     }, {
0193         .nvmem_name = "fuse",
0194         .cell_name = "tsensor-pllx",
0195         .dev_id = "700e2000.thermal-sensor",
0196         .con_id = "pllx",
0197     },
0198 };
0199 
0200 static const struct tegra_fuse_info tegra124_fuse_info = {
0201     .read = tegra30_fuse_read,
0202     .size = 0x300,
0203     .spare = 0x200,
0204 };
0205 
0206 const struct tegra_fuse_soc tegra124_fuse_soc = {
0207     .init = tegra30_fuse_init,
0208     .speedo_init = tegra124_init_speedo_data,
0209     .info = &tegra124_fuse_info,
0210     .lookups = tegra124_fuse_lookups,
0211     .num_lookups = ARRAY_SIZE(tegra124_fuse_lookups),
0212     .soc_attr_group = &tegra_soc_attr_group,
0213     .clk_suspend_on = true,
0214 };
0215 #endif
0216 
0217 #if defined(CONFIG_ARCH_TEGRA_210_SOC)
0218 static const struct nvmem_cell_lookup tegra210_fuse_lookups[] = {
0219     {
0220         .nvmem_name = "fuse",
0221         .cell_name = "tsensor-cpu1",
0222         .dev_id = "700e2000.thermal-sensor",
0223         .con_id = "cpu1",
0224     }, {
0225         .nvmem_name = "fuse",
0226         .cell_name = "tsensor-cpu2",
0227         .dev_id = "700e2000.thermal-sensor",
0228         .con_id = "cpu2",
0229     }, {
0230         .nvmem_name = "fuse",
0231         .cell_name = "tsensor-cpu0",
0232         .dev_id = "700e2000.thermal-sensor",
0233         .con_id = "cpu0",
0234     }, {
0235         .nvmem_name = "fuse",
0236         .cell_name = "xusb-pad-calibration",
0237         .dev_id = "7009f000.padctl",
0238         .con_id = "calibration",
0239     }, {
0240         .nvmem_name = "fuse",
0241         .cell_name = "tsensor-cpu3",
0242         .dev_id = "700e2000.thermal-sensor",
0243         .con_id = "cpu3",
0244     }, {
0245         .nvmem_name = "fuse",
0246         .cell_name = "sata-calibration",
0247         .dev_id = "70020000.sata",
0248         .con_id = "calibration",
0249     }, {
0250         .nvmem_name = "fuse",
0251         .cell_name = "tsensor-gpu",
0252         .dev_id = "700e2000.thermal-sensor",
0253         .con_id = "gpu",
0254     }, {
0255         .nvmem_name = "fuse",
0256         .cell_name = "tsensor-mem0",
0257         .dev_id = "700e2000.thermal-sensor",
0258         .con_id = "mem0",
0259     }, {
0260         .nvmem_name = "fuse",
0261         .cell_name = "tsensor-mem1",
0262         .dev_id = "700e2000.thermal-sensor",
0263         .con_id = "mem1",
0264     }, {
0265         .nvmem_name = "fuse",
0266         .cell_name = "tsensor-pllx",
0267         .dev_id = "700e2000.thermal-sensor",
0268         .con_id = "pllx",
0269     }, {
0270         .nvmem_name = "fuse",
0271         .cell_name = "tsensor-common",
0272         .dev_id = "700e2000.thermal-sensor",
0273         .con_id = "common",
0274     }, {
0275         .nvmem_name = "fuse",
0276         .cell_name = "gpu-calibration",
0277         .dev_id = "57000000.gpu",
0278         .con_id = "calibration",
0279     }, {
0280         .nvmem_name = "fuse",
0281         .cell_name = "xusb-pad-calibration-ext",
0282         .dev_id = "7009f000.padctl",
0283         .con_id = "calibration-ext",
0284     },
0285 };
0286 
0287 static const struct tegra_fuse_info tegra210_fuse_info = {
0288     .read = tegra30_fuse_read,
0289     .size = 0x300,
0290     .spare = 0x280,
0291 };
0292 
0293 const struct tegra_fuse_soc tegra210_fuse_soc = {
0294     .init = tegra30_fuse_init,
0295     .speedo_init = tegra210_init_speedo_data,
0296     .info = &tegra210_fuse_info,
0297     .lookups = tegra210_fuse_lookups,
0298     .num_lookups = ARRAY_SIZE(tegra210_fuse_lookups),
0299     .soc_attr_group = &tegra_soc_attr_group,
0300     .clk_suspend_on = false,
0301 };
0302 #endif
0303 
0304 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
0305 static const struct nvmem_cell_lookup tegra186_fuse_lookups[] = {
0306     {
0307         .nvmem_name = "fuse",
0308         .cell_name = "xusb-pad-calibration",
0309         .dev_id = "3520000.padctl",
0310         .con_id = "calibration",
0311     }, {
0312         .nvmem_name = "fuse",
0313         .cell_name = "xusb-pad-calibration-ext",
0314         .dev_id = "3520000.padctl",
0315         .con_id = "calibration-ext",
0316     },
0317 };
0318 
0319 static const struct tegra_fuse_info tegra186_fuse_info = {
0320     .read = tegra30_fuse_read,
0321     .size = 0x300,
0322     .spare = 0x280,
0323 };
0324 
0325 const struct tegra_fuse_soc tegra186_fuse_soc = {
0326     .init = tegra30_fuse_init,
0327     .info = &tegra186_fuse_info,
0328     .lookups = tegra186_fuse_lookups,
0329     .num_lookups = ARRAY_SIZE(tegra186_fuse_lookups),
0330     .soc_attr_group = &tegra_soc_attr_group,
0331     .clk_suspend_on = false,
0332 };
0333 #endif
0334 
0335 #if defined(CONFIG_ARCH_TEGRA_194_SOC)
0336 static const struct nvmem_cell_lookup tegra194_fuse_lookups[] = {
0337     {
0338         .nvmem_name = "fuse",
0339         .cell_name = "xusb-pad-calibration",
0340         .dev_id = "3520000.padctl",
0341         .con_id = "calibration",
0342     }, {
0343         .nvmem_name = "fuse",
0344         .cell_name = "xusb-pad-calibration-ext",
0345         .dev_id = "3520000.padctl",
0346         .con_id = "calibration-ext",
0347     }, {
0348         .nvmem_name = "fuse",
0349         .cell_name = "gpu-gcplex-config-fuse",
0350         .dev_id = "17000000.gpu",
0351         .con_id = "gcplex-config-fuse",
0352     }, {
0353         .nvmem_name = "fuse",
0354         .cell_name = "gpu-pdi0",
0355         .dev_id = "17000000.gpu",
0356         .con_id = "pdi0",
0357     }, {
0358         .nvmem_name = "fuse",
0359         .cell_name = "gpu-pdi1",
0360         .dev_id = "17000000.gpu",
0361         .con_id = "pdi1",
0362     },
0363 };
0364 
0365 static const struct tegra_fuse_info tegra194_fuse_info = {
0366     .read = tegra30_fuse_read,
0367     .size = 0x300,
0368     .spare = 0x280,
0369 };
0370 
0371 const struct tegra_fuse_soc tegra194_fuse_soc = {
0372     .init = tegra30_fuse_init,
0373     .info = &tegra194_fuse_info,
0374     .lookups = tegra194_fuse_lookups,
0375     .num_lookups = ARRAY_SIZE(tegra194_fuse_lookups),
0376     .soc_attr_group = &tegra194_soc_attr_group,
0377     .clk_suspend_on = false,
0378 };
0379 #endif
0380 
0381 #if defined(CONFIG_ARCH_TEGRA_234_SOC)
0382 static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = {
0383     {
0384         .nvmem_name = "fuse",
0385         .cell_name = "xusb-pad-calibration",
0386         .dev_id = "3520000.padctl",
0387         .con_id = "calibration",
0388     }, {
0389         .nvmem_name = "fuse",
0390         .cell_name = "xusb-pad-calibration-ext",
0391         .dev_id = "3520000.padctl",
0392         .con_id = "calibration-ext",
0393     },
0394 };
0395 
0396 static const struct tegra_fuse_info tegra234_fuse_info = {
0397     .read = tegra30_fuse_read,
0398     .size = 0x300,
0399     .spare = 0x280,
0400 };
0401 
0402 const struct tegra_fuse_soc tegra234_fuse_soc = {
0403     .init = tegra30_fuse_init,
0404     .info = &tegra234_fuse_info,
0405     .lookups = tegra234_fuse_lookups,
0406     .num_lookups = ARRAY_SIZE(tegra234_fuse_lookups),
0407     .soc_attr_group = &tegra194_soc_attr_group,
0408     .clk_suspend_on = false,
0409 };
0410 #endif