1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. 4 */ 5 6 #include <linux/device.h> 7 #include <linux/clk.h> 8 #include <linux/err.h> 9 #include <linux/io.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> 15 16 #include <soc/tegra/fuse.h> 17 18 #include "fuse.h" 19 20 #define FUSE_BEGIN 0x100 21 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 30 31 #define FUSE_HAS_REVISION_INFO BIT(0) 32 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 static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset) 40 { 41 if (WARN_ON(!fuse->base)) 42 return 0; 43 44 return readl_relaxed(fuse->base + FUSE_BEGIN + offset); 45 } 46 47 static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset) 48 { 49 u32 value; 50 int err; 51 52 err = clk_prepare_enable(fuse->clk); 53 if (err < 0) { 54 dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err); 55 return 0; 56 } 57 58 value = readl_relaxed(fuse->base + FUSE_BEGIN + offset); 59 60 clk_disable_unprepare(fuse->clk); 61 62 return value; 63 } 64 65 static void __init tegra30_fuse_add_randomness(void) 66 { 67 u32 randomness[12]; 68 69 randomness[0] = tegra_sku_info.sku_id; 70 randomness[1] = tegra_read_straps(); 71 randomness[2] = tegra_read_chipid(); 72 randomness[3] = tegra_sku_info.cpu_process_id << 16; 73 randomness[3] |= tegra_sku_info.soc_process_id; 74 randomness[4] = tegra_sku_info.cpu_speedo_id << 16; 75 randomness[4] |= tegra_sku_info.soc_speedo_id; 76 randomness[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE); 77 randomness[6] = tegra_fuse_read_early(FUSE_FAB_CODE); 78 randomness[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0); 79 randomness[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1); 80 randomness[9] = tegra_fuse_read_early(FUSE_WAFER_ID); 81 randomness[10] = tegra_fuse_read_early(FUSE_X_COORDINATE); 82 randomness[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE); 83 84 add_device_randomness(randomness, sizeof(randomness)); 85 } 86 87 static void __init tegra30_fuse_init(struct tegra_fuse *fuse) 88 { 89 fuse->read_early = tegra30_fuse_read_early; 90 fuse->read = tegra30_fuse_read; 91 92 tegra_init_revision(); 93 94 if (fuse->soc->speedo_init) 95 fuse->soc->speedo_init(&tegra_sku_info); 96 97 tegra30_fuse_add_randomness(); 98 } 99 #endif 100 101 #ifdef CONFIG_ARCH_TEGRA_3x_SOC 102 static const struct tegra_fuse_info tegra30_fuse_info = { 103 .read = tegra30_fuse_read, 104 .size = 0x2a4, 105 .spare = 0x144, 106 }; 107 108 const struct tegra_fuse_soc tegra30_fuse_soc = { 109 .init = tegra30_fuse_init, 110 .speedo_init = tegra30_init_speedo_data, 111 .info = &tegra30_fuse_info, 112 }; 113 #endif 114 115 #ifdef CONFIG_ARCH_TEGRA_114_SOC 116 static const struct tegra_fuse_info tegra114_fuse_info = { 117 .read = tegra30_fuse_read, 118 .size = 0x2a0, 119 .spare = 0x180, 120 }; 121 122 const struct tegra_fuse_soc tegra114_fuse_soc = { 123 .init = tegra30_fuse_init, 124 .speedo_init = tegra114_init_speedo_data, 125 .info = &tegra114_fuse_info, 126 }; 127 #endif 128 129 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) 130 static const struct tegra_fuse_info tegra124_fuse_info = { 131 .read = tegra30_fuse_read, 132 .size = 0x300, 133 .spare = 0x200, 134 }; 135 136 const struct tegra_fuse_soc tegra124_fuse_soc = { 137 .init = tegra30_fuse_init, 138 .speedo_init = tegra124_init_speedo_data, 139 .info = &tegra124_fuse_info, 140 }; 141 #endif 142 143 #if defined(CONFIG_ARCH_TEGRA_210_SOC) 144 static const struct tegra_fuse_info tegra210_fuse_info = { 145 .read = tegra30_fuse_read, 146 .size = 0x300, 147 .spare = 0x280, 148 }; 149 150 const struct tegra_fuse_soc tegra210_fuse_soc = { 151 .init = tegra30_fuse_init, 152 .speedo_init = tegra210_init_speedo_data, 153 .info = &tegra210_fuse_info, 154 }; 155 #endif 156 157 #if defined(CONFIG_ARCH_TEGRA_186_SOC) 158 static const struct tegra_fuse_info tegra186_fuse_info = { 159 .read = tegra30_fuse_read, 160 .size = 0x300, 161 .spare = 0x280, 162 }; 163 164 const struct tegra_fuse_soc tegra186_fuse_soc = { 165 .init = tegra30_fuse_init, 166 .info = &tegra186_fuse_info, 167 }; 168 #endif 169