0001
0002
0003
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
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