linux/drivers/soc/tegra/fuse/fuse-tegra30.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  15 *
  16 */
  17
  18#include <linux/device.h>
  19#include <linux/clk.h>
  20#include <linux/err.h>
  21#include <linux/io.h>
  22#include <linux/kernel.h>
  23#include <linux/of_device.h>
  24#include <linux/of_address.h>
  25#include <linux/platform_device.h>
  26#include <linux/random.h>
  27
  28#include <soc/tegra/fuse.h>
  29
  30#include "fuse.h"
  31
  32#define FUSE_BEGIN      0x100
  33
  34/* Tegra30 and later */
  35#define FUSE_VENDOR_CODE        0x100
  36#define FUSE_FAB_CODE           0x104
  37#define FUSE_LOT_CODE_0         0x108
  38#define FUSE_LOT_CODE_1         0x10c
  39#define FUSE_WAFER_ID           0x110
  40#define FUSE_X_COORDINATE       0x114
  41#define FUSE_Y_COORDINATE       0x118
  42
  43#define FUSE_HAS_REVISION_INFO  BIT(0)
  44
  45#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
  46    defined(CONFIG_ARCH_TEGRA_114_SOC) || \
  47    defined(CONFIG_ARCH_TEGRA_124_SOC) || \
  48    defined(CONFIG_ARCH_TEGRA_132_SOC) || \
  49    defined(CONFIG_ARCH_TEGRA_210_SOC) || \
  50    defined(CONFIG_ARCH_TEGRA_186_SOC)
  51static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset)
  52{
  53        if (WARN_ON(!fuse->base))
  54                return 0;
  55
  56        return readl_relaxed(fuse->base + FUSE_BEGIN + offset);
  57}
  58
  59static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
  60{
  61        u32 value;
  62        int err;
  63
  64        err = clk_prepare_enable(fuse->clk);
  65        if (err < 0) {
  66                dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err);
  67                return 0;
  68        }
  69
  70        value = readl_relaxed(fuse->base + FUSE_BEGIN + offset);
  71
  72        clk_disable_unprepare(fuse->clk);
  73
  74        return value;
  75}
  76
  77static void __init tegra30_fuse_add_randomness(void)
  78{
  79        u32 randomness[12];
  80
  81        randomness[0] = tegra_sku_info.sku_id;
  82        randomness[1] = tegra_read_straps();
  83        randomness[2] = tegra_read_chipid();
  84        randomness[3] = tegra_sku_info.cpu_process_id << 16;
  85        randomness[3] |= tegra_sku_info.soc_process_id;
  86        randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
  87        randomness[4] |= tegra_sku_info.soc_speedo_id;
  88        randomness[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE);
  89        randomness[6] = tegra_fuse_read_early(FUSE_FAB_CODE);
  90        randomness[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0);
  91        randomness[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1);
  92        randomness[9] = tegra_fuse_read_early(FUSE_WAFER_ID);
  93        randomness[10] = tegra_fuse_read_early(FUSE_X_COORDINATE);
  94        randomness[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE);
  95
  96        add_device_randomness(randomness, sizeof(randomness));
  97}
  98
  99static void __init tegra30_fuse_init(struct tegra_fuse *fuse)
 100{
 101        fuse->read_early = tegra30_fuse_read_early;
 102        fuse->read = tegra30_fuse_read;
 103
 104        tegra_init_revision();
 105
 106        if (fuse->soc->speedo_init)
 107                fuse->soc->speedo_init(&tegra_sku_info);
 108
 109        tegra30_fuse_add_randomness();
 110}
 111#endif
 112
 113#ifdef CONFIG_ARCH_TEGRA_3x_SOC
 114static const struct tegra_fuse_info tegra30_fuse_info = {
 115        .read = tegra30_fuse_read,
 116        .size = 0x2a4,
 117        .spare = 0x144,
 118};
 119
 120const struct tegra_fuse_soc tegra30_fuse_soc = {
 121        .init = tegra30_fuse_init,
 122        .speedo_init = tegra30_init_speedo_data,
 123        .info = &tegra30_fuse_info,
 124};
 125#endif
 126
 127#ifdef CONFIG_ARCH_TEGRA_114_SOC
 128static const struct tegra_fuse_info tegra114_fuse_info = {
 129        .read = tegra30_fuse_read,
 130        .size = 0x2a0,
 131        .spare = 0x180,
 132};
 133
 134const struct tegra_fuse_soc tegra114_fuse_soc = {
 135        .init = tegra30_fuse_init,
 136        .speedo_init = tegra114_init_speedo_data,
 137        .info = &tegra114_fuse_info,
 138};
 139#endif
 140
 141#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
 142static const struct tegra_fuse_info tegra124_fuse_info = {
 143        .read = tegra30_fuse_read,
 144        .size = 0x300,
 145        .spare = 0x200,
 146};
 147
 148const struct tegra_fuse_soc tegra124_fuse_soc = {
 149        .init = tegra30_fuse_init,
 150        .speedo_init = tegra124_init_speedo_data,
 151        .info = &tegra124_fuse_info,
 152};
 153#endif
 154
 155#if defined(CONFIG_ARCH_TEGRA_210_SOC)
 156static const struct tegra_fuse_info tegra210_fuse_info = {
 157        .read = tegra30_fuse_read,
 158        .size = 0x300,
 159        .spare = 0x280,
 160};
 161
 162const struct tegra_fuse_soc tegra210_fuse_soc = {
 163        .init = tegra30_fuse_init,
 164        .speedo_init = tegra210_init_speedo_data,
 165        .info = &tegra210_fuse_info,
 166};
 167#endif
 168
 169#if defined(CONFIG_ARCH_TEGRA_186_SOC)
 170static const struct tegra_fuse_info tegra186_fuse_info = {
 171        .read = tegra30_fuse_read,
 172        .size = 0x300,
 173        .spare = 0x280,
 174};
 175
 176const struct tegra_fuse_soc tegra186_fuse_soc = {
 177        .init = tegra30_fuse_init,
 178        .info = &tegra186_fuse_info,
 179};
 180#endif
 181