root/drivers/soc/tegra/fuse/fuse-tegra.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fuse_readb
  2. fuse_read
  3. tegra_fuse_create_sysfs
  4. tegra_fuse_probe
  5. tegra_fuse_read_spare
  6. tegra_fuse_read_early
  7. tegra_fuse_readl
  8. tegra_enable_fuse_clk
  9. tegra_soc_device_register
  10. tegra_init_fuse
  11. tegra_init_soc

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
   4  */
   5 
   6 #include <linux/clk.h>
   7 #include <linux/device.h>
   8 #include <linux/kobject.h>
   9 #include <linux/init.h>
  10 #include <linux/io.h>
  11 #include <linux/of.h>
  12 #include <linux/of_address.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/slab.h>
  15 #include <linux/sys_soc.h>
  16 
  17 #include <soc/tegra/common.h>
  18 #include <soc/tegra/fuse.h>
  19 
  20 #include "fuse.h"
  21 
  22 struct tegra_sku_info tegra_sku_info;
  23 EXPORT_SYMBOL(tegra_sku_info);
  24 
  25 static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
  26         [TEGRA_REVISION_UNKNOWN] = "unknown",
  27         [TEGRA_REVISION_A01]     = "A01",
  28         [TEGRA_REVISION_A02]     = "A02",
  29         [TEGRA_REVISION_A03]     = "A03",
  30         [TEGRA_REVISION_A03p]    = "A03 prime",
  31         [TEGRA_REVISION_A04]     = "A04",
  32 };
  33 
  34 static u8 fuse_readb(struct tegra_fuse *fuse, unsigned int offset)
  35 {
  36         u32 val;
  37 
  38         val = fuse->read(fuse, round_down(offset, 4));
  39         val >>= (offset % 4) * 8;
  40         val &= 0xff;
  41 
  42         return val;
  43 }
  44 
  45 static ssize_t fuse_read(struct file *fd, struct kobject *kobj,
  46                          struct bin_attribute *attr, char *buf,
  47                          loff_t pos, size_t size)
  48 {
  49         struct device *dev = kobj_to_dev(kobj);
  50         struct tegra_fuse *fuse = dev_get_drvdata(dev);
  51         int i;
  52 
  53         if (pos < 0 || pos >= attr->size)
  54                 return 0;
  55 
  56         if (size > attr->size - pos)
  57                 size = attr->size - pos;
  58 
  59         for (i = 0; i < size; i++)
  60                 buf[i] = fuse_readb(fuse, pos + i);
  61 
  62         return i;
  63 }
  64 
  65 static struct bin_attribute fuse_bin_attr = {
  66         .attr = { .name = "fuse", .mode = S_IRUGO, },
  67         .read = fuse_read,
  68 };
  69 
  70 static int tegra_fuse_create_sysfs(struct device *dev, unsigned int size,
  71                                    const struct tegra_fuse_info *info)
  72 {
  73         fuse_bin_attr.size = size;
  74 
  75         return device_create_bin_file(dev, &fuse_bin_attr);
  76 }
  77 
  78 static const struct of_device_id car_match[] __initconst = {
  79         { .compatible = "nvidia,tegra20-car", },
  80         { .compatible = "nvidia,tegra30-car", },
  81         { .compatible = "nvidia,tegra114-car", },
  82         { .compatible = "nvidia,tegra124-car", },
  83         { .compatible = "nvidia,tegra132-car", },
  84         { .compatible = "nvidia,tegra210-car", },
  85         {},
  86 };
  87 
  88 static struct tegra_fuse *fuse = &(struct tegra_fuse) {
  89         .base = NULL,
  90         .soc = NULL,
  91 };
  92 
  93 static const struct of_device_id tegra_fuse_match[] = {
  94 #ifdef CONFIG_ARCH_TEGRA_186_SOC
  95         { .compatible = "nvidia,tegra186-efuse", .data = &tegra186_fuse_soc },
  96 #endif
  97 #ifdef CONFIG_ARCH_TEGRA_210_SOC
  98         { .compatible = "nvidia,tegra210-efuse", .data = &tegra210_fuse_soc },
  99 #endif
 100 #ifdef CONFIG_ARCH_TEGRA_132_SOC
 101         { .compatible = "nvidia,tegra132-efuse", .data = &tegra124_fuse_soc },
 102 #endif
 103 #ifdef CONFIG_ARCH_TEGRA_124_SOC
 104         { .compatible = "nvidia,tegra124-efuse", .data = &tegra124_fuse_soc },
 105 #endif
 106 #ifdef CONFIG_ARCH_TEGRA_114_SOC
 107         { .compatible = "nvidia,tegra114-efuse", .data = &tegra114_fuse_soc },
 108 #endif
 109 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 110         { .compatible = "nvidia,tegra30-efuse", .data = &tegra30_fuse_soc },
 111 #endif
 112 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 113         { .compatible = "nvidia,tegra20-efuse", .data = &tegra20_fuse_soc },
 114 #endif
 115         { /* sentinel */ }
 116 };
 117 
 118 static int tegra_fuse_probe(struct platform_device *pdev)
 119 {
 120         void __iomem *base = fuse->base;
 121         struct resource *res;
 122         int err;
 123 
 124         /* take over the memory region from the early initialization */
 125         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 126         fuse->phys = res->start;
 127         fuse->base = devm_ioremap_resource(&pdev->dev, res);
 128         if (IS_ERR(fuse->base)) {
 129                 err = PTR_ERR(fuse->base);
 130                 fuse->base = base;
 131                 return err;
 132         }
 133 
 134         fuse->clk = devm_clk_get(&pdev->dev, "fuse");
 135         if (IS_ERR(fuse->clk)) {
 136                 if (PTR_ERR(fuse->clk) != -EPROBE_DEFER)
 137                         dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
 138                                 PTR_ERR(fuse->clk));
 139 
 140                 fuse->base = base;
 141                 return PTR_ERR(fuse->clk);
 142         }
 143 
 144         platform_set_drvdata(pdev, fuse);
 145         fuse->dev = &pdev->dev;
 146 
 147         if (fuse->soc->probe) {
 148                 err = fuse->soc->probe(fuse);
 149                 if (err < 0) {
 150                         fuse->base = base;
 151                         return err;
 152                 }
 153         }
 154 
 155         if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size,
 156                                     fuse->soc->info))
 157                 return -ENODEV;
 158 
 159         /* release the early I/O memory mapping */
 160         iounmap(base);
 161 
 162         return 0;
 163 }
 164 
 165 static struct platform_driver tegra_fuse_driver = {
 166         .driver = {
 167                 .name = "tegra-fuse",
 168                 .of_match_table = tegra_fuse_match,
 169                 .suppress_bind_attrs = true,
 170         },
 171         .probe = tegra_fuse_probe,
 172 };
 173 builtin_platform_driver(tegra_fuse_driver);
 174 
 175 bool __init tegra_fuse_read_spare(unsigned int spare)
 176 {
 177         unsigned int offset = fuse->soc->info->spare + spare * 4;
 178 
 179         return fuse->read_early(fuse, offset) & 1;
 180 }
 181 
 182 u32 __init tegra_fuse_read_early(unsigned int offset)
 183 {
 184         return fuse->read_early(fuse, offset);
 185 }
 186 
 187 int tegra_fuse_readl(unsigned long offset, u32 *value)
 188 {
 189         if (!fuse->read)
 190                 return -EPROBE_DEFER;
 191 
 192         *value = fuse->read(fuse, offset);
 193 
 194         return 0;
 195 }
 196 EXPORT_SYMBOL(tegra_fuse_readl);
 197 
 198 static void tegra_enable_fuse_clk(void __iomem *base)
 199 {
 200         u32 reg;
 201 
 202         reg = readl_relaxed(base + 0x48);
 203         reg |= 1 << 28;
 204         writel(reg, base + 0x48);
 205 
 206         /*
 207          * Enable FUSE clock. This needs to be hardcoded because the clock
 208          * subsystem is not active during early boot.
 209          */
 210         reg = readl(base + 0x14);
 211         reg |= 1 << 7;
 212         writel(reg, base + 0x14);
 213 }
 214 
 215 struct device * __init tegra_soc_device_register(void)
 216 {
 217         struct soc_device_attribute *attr;
 218         struct soc_device *dev;
 219 
 220         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
 221         if (!attr)
 222                 return NULL;
 223 
 224         attr->family = kasprintf(GFP_KERNEL, "Tegra");
 225         attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_sku_info.revision);
 226         attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id());
 227 
 228         dev = soc_device_register(attr);
 229         if (IS_ERR(dev)) {
 230                 kfree(attr->soc_id);
 231                 kfree(attr->revision);
 232                 kfree(attr->family);
 233                 kfree(attr);
 234                 return ERR_CAST(dev);
 235         }
 236 
 237         return soc_device_to_device(dev);
 238 }
 239 
 240 static int __init tegra_init_fuse(void)
 241 {
 242         const struct of_device_id *match;
 243         struct device_node *np;
 244         struct resource regs;
 245 
 246         tegra_init_apbmisc();
 247 
 248         np = of_find_matching_node_and_match(NULL, tegra_fuse_match, &match);
 249         if (!np) {
 250                 /*
 251                  * Fall back to legacy initialization for 32-bit ARM only. All
 252                  * 64-bit ARM device tree files for Tegra are required to have
 253                  * a FUSE node.
 254                  *
 255                  * This is for backwards-compatibility with old device trees
 256                  * that didn't contain a FUSE node.
 257                  */
 258                 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
 259                         u8 chip = tegra_get_chip_id();
 260 
 261                         regs.start = 0x7000f800;
 262                         regs.end = 0x7000fbff;
 263                         regs.flags = IORESOURCE_MEM;
 264 
 265                         switch (chip) {
 266 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 267                         case TEGRA20:
 268                                 fuse->soc = &tegra20_fuse_soc;
 269                                 break;
 270 #endif
 271 
 272 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 273                         case TEGRA30:
 274                                 fuse->soc = &tegra30_fuse_soc;
 275                                 break;
 276 #endif
 277 
 278 #ifdef CONFIG_ARCH_TEGRA_114_SOC
 279                         case TEGRA114:
 280                                 fuse->soc = &tegra114_fuse_soc;
 281                                 break;
 282 #endif
 283 
 284 #ifdef CONFIG_ARCH_TEGRA_124_SOC
 285                         case TEGRA124:
 286                                 fuse->soc = &tegra124_fuse_soc;
 287                                 break;
 288 #endif
 289 
 290                         default:
 291                                 pr_warn("Unsupported SoC: %02x\n", chip);
 292                                 break;
 293                         }
 294                 } else {
 295                         /*
 296                          * At this point we're not running on Tegra, so play
 297                          * nice with multi-platform kernels.
 298                          */
 299                         return 0;
 300                 }
 301         } else {
 302                 /*
 303                  * Extract information from the device tree if we've found a
 304                  * matching node.
 305                  */
 306                 if (of_address_to_resource(np, 0, &regs) < 0) {
 307                         pr_err("failed to get FUSE register\n");
 308                         return -ENXIO;
 309                 }
 310 
 311                 fuse->soc = match->data;
 312         }
 313 
 314         np = of_find_matching_node(NULL, car_match);
 315         if (np) {
 316                 void __iomem *base = of_iomap(np, 0);
 317                 if (base) {
 318                         tegra_enable_fuse_clk(base);
 319                         iounmap(base);
 320                 } else {
 321                         pr_err("failed to map clock registers\n");
 322                         return -ENXIO;
 323                 }
 324         }
 325 
 326         fuse->base = ioremap_nocache(regs.start, resource_size(&regs));
 327         if (!fuse->base) {
 328                 pr_err("failed to map FUSE registers\n");
 329                 return -ENXIO;
 330         }
 331 
 332         fuse->soc->init(fuse);
 333 
 334         pr_info("Tegra Revision: %s SKU: %d CPU Process: %d SoC Process: %d\n",
 335                 tegra_revision_name[tegra_sku_info.revision],
 336                 tegra_sku_info.sku_id, tegra_sku_info.cpu_process_id,
 337                 tegra_sku_info.soc_process_id);
 338         pr_debug("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n",
 339                  tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);
 340 
 341 
 342         return 0;
 343 }
 344 early_initcall(tegra_init_fuse);
 345 
 346 #ifdef CONFIG_ARM64
 347 static int __init tegra_init_soc(void)
 348 {
 349         struct device_node *np;
 350         struct device *soc;
 351 
 352         /* make sure we're running on Tegra */
 353         np = of_find_matching_node(NULL, tegra_fuse_match);
 354         if (!np)
 355                 return 0;
 356 
 357         of_node_put(np);
 358 
 359         soc = tegra_soc_device_register();
 360         if (IS_ERR(soc)) {
 361                 pr_err("failed to register SoC device: %ld\n", PTR_ERR(soc));
 362                 return PTR_ERR(soc);
 363         }
 364 
 365         return 0;
 366 }
 367 device_initcall(tegra_init_soc);
 368 #endif

/* [<][>][^][v][top][bottom][index][help] */