linux/drivers/soc/tegra/fuse/fuse-tegra30.c
<<
>>
Prefs
   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)
  39static 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
  47static 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
  65static 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
  87static 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
 102static const struct tegra_fuse_info tegra30_fuse_info = {
 103        .read = tegra30_fuse_read,
 104        .size = 0x2a4,
 105        .spare = 0x144,
 106};
 107
 108const 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
 116static const struct tegra_fuse_info tegra114_fuse_info = {
 117        .read = tegra30_fuse_read,
 118        .size = 0x2a0,
 119        .spare = 0x180,
 120};
 121
 122const 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)
 130static const struct tegra_fuse_info tegra124_fuse_info = {
 131        .read = tegra30_fuse_read,
 132        .size = 0x300,
 133        .spare = 0x200,
 134};
 135
 136const 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)
 144static const struct tegra_fuse_info tegra210_fuse_info = {
 145        .read = tegra30_fuse_read,
 146        .size = 0x300,
 147        .spare = 0x280,
 148};
 149
 150const 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)
 158static const struct tegra_fuse_info tegra186_fuse_info = {
 159        .read = tegra30_fuse_read,
 160        .size = 0x300,
 161        .spare = 0x280,
 162};
 163
 164const struct tegra_fuse_soc tegra186_fuse_soc = {
 165        .init = tegra30_fuse_init,
 166        .info = &tegra186_fuse_info,
 167};
 168#endif
 169