1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2013-2022, 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/nvmem-consumer.h> 12 #include <linux/nvmem-provider.h> 13 #include <linux/of_device.h> 14 #include <linux/of_address.h> 15 #include <linux/platform_device.h> 16 #include <linux/pm_runtime.h> 17 #include <linux/random.h> 18 19 #include <soc/tegra/fuse.h> 20 21 #include "fuse.h" 22 23 #define FUSE_BEGIN 0x100 24 25 /* Tegra30 and later */ 26 #define FUSE_VENDOR_CODE 0x100 27 #define FUSE_FAB_CODE 0x104 28 #define FUSE_LOT_CODE_0 0x108 29 #define FUSE_LOT_CODE_1 0x10c 30 #define FUSE_WAFER_ID 0x110 31 #define FUSE_X_COORDINATE 0x114 32 #define FUSE_Y_COORDINATE 0x118 33 34 #define FUSE_HAS_REVISION_INFO BIT(0) 35 36 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \ 37 defined(CONFIG_ARCH_TEGRA_114_SOC) || \ 38 defined(CONFIG_ARCH_TEGRA_124_SOC) || \ 39 defined(CONFIG_ARCH_TEGRA_132_SOC) || \ 40 defined(CONFIG_ARCH_TEGRA_210_SOC) || \ 41 defined(CONFIG_ARCH_TEGRA_186_SOC) || \ 42 defined(CONFIG_ARCH_TEGRA_194_SOC) || \ 43 defined(CONFIG_ARCH_TEGRA_234_SOC) 44 static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset) 45 { 46 if (WARN_ON(!fuse->base)) 47 return 0; 48 49 return readl_relaxed(fuse->base + FUSE_BEGIN + offset); 50 } 51 52 static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset) 53 { 54 u32 value; 55 int err; 56 57 err = pm_runtime_resume_and_get(fuse->dev); 58 if (err) 59 return 0; 60 61 value = readl_relaxed(fuse->base + FUSE_BEGIN + offset); 62 63 pm_runtime_put(fuse->dev); 64 65 return value; 66 } 67 68 static void __init tegra30_fuse_add_randomness(void) 69 { 70 u32 randomness[12]; 71 72 randomness[0] = tegra_sku_info.sku_id; 73 randomness[1] = tegra_read_straps(); 74 randomness[2] = tegra_read_chipid(); 75 randomness[3] = tegra_sku_info.cpu_process_id << 16; 76 randomness[3] |= tegra_sku_info.soc_process_id; 77 randomness[4] = tegra_sku_info.cpu_speedo_id << 16; 78 randomness[4] |= tegra_sku_info.soc_speedo_id; 79 randomness[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE); 80 randomness[6] = tegra_fuse_read_early(FUSE_FAB_CODE); 81 randomness[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0); 82 randomness[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1); 83 randomness[9] = tegra_fuse_read_early(FUSE_WAFER_ID); 84 randomness[10] = tegra_fuse_read_early(FUSE_X_COORDINATE); 85 randomness[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE); 86 87 add_device_randomness(randomness, sizeof(randomness)); 88 } 89 90 static void __init tegra30_fuse_init(struct tegra_fuse *fuse) 91 { 92 fuse->read_early = tegra30_fuse_read_early; 93 fuse->read = tegra30_fuse_read; 94 95 tegra_init_revision(); 96 97 if (fuse->soc->speedo_init) 98 fuse->soc->speedo_init(&tegra_sku_info); 99 100 tegra30_fuse_add_randomness(); 101 } 102 #endif 103 104 #ifdef CONFIG_ARCH_TEGRA_3x_SOC 105 static const struct tegra_fuse_info tegra30_fuse_info = { 106 .read = tegra30_fuse_read, 107 .size = 0x2a4, 108 .spare = 0x144, 109 }; 110 111 const struct tegra_fuse_soc tegra30_fuse_soc = { 112 .init = tegra30_fuse_init, 113 .speedo_init = tegra30_init_speedo_data, 114 .info = &tegra30_fuse_info, 115 .soc_attr_group = &tegra_soc_attr_group, 116 .clk_suspend_on = false, 117 }; 118 #endif 119 120 #ifdef CONFIG_ARCH_TEGRA_114_SOC 121 static const struct tegra_fuse_info tegra114_fuse_info = { 122 .read = tegra30_fuse_read, 123 .size = 0x2a0, 124 .spare = 0x180, 125 }; 126 127 const struct tegra_fuse_soc tegra114_fuse_soc = { 128 .init = tegra30_fuse_init, 129 .speedo_init = tegra114_init_speedo_data, 130 .info = &tegra114_fuse_info, 131 .soc_attr_group = &tegra_soc_attr_group, 132 .clk_suspend_on = false, 133 }; 134 #endif 135 136 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) 137 static const struct nvmem_cell_info tegra124_fuse_cells[] = { 138 { 139 .name = "tsensor-cpu1", 140 .offset = 0x084, 141 .bytes = 4, 142 .bit_offset = 0, 143 .nbits = 32, 144 }, { 145 .name = "tsensor-cpu2", 146 .offset = 0x088, 147 .bytes = 4, 148 .bit_offset = 0, 149 .nbits = 32, 150 }, { 151 .name = "tsensor-cpu0", 152 .offset = 0x098, 153 .bytes = 4, 154 .bit_offset = 0, 155 .nbits = 32, 156 }, { 157 .name = "xusb-pad-calibration", 158 .offset = 0x0f0, 159 .bytes = 4, 160 .bit_offset = 0, 161 .nbits = 32, 162 }, { 163 .name = "tsensor-cpu3", 164 .offset = 0x12c, 165 .bytes = 4, 166 .bit_offset = 0, 167 .nbits = 32, 168 }, { 169 .name = "sata-calibration", 170 .offset = 0x124, 171 .bytes = 4, 172 .bit_offset = 0, 173 .nbits = 32, 174 }, { 175 .name = "tsensor-gpu", 176 .offset = 0x154, 177 .bytes = 4, 178 .bit_offset = 0, 179 .nbits = 32, 180 }, { 181 .name = "tsensor-mem0", 182 .offset = 0x158, 183 .bytes = 4, 184 .bit_offset = 0, 185 .nbits = 32, 186 }, { 187 .name = "tsensor-mem1", 188 .offset = 0x15c, 189 .bytes = 4, 190 .bit_offset = 0, 191 .nbits = 32, 192 }, { 193 .name = "tsensor-pllx", 194 .offset = 0x160, 195 .bytes = 4, 196 .bit_offset = 0, 197 .nbits = 32, 198 }, { 199 .name = "tsensor-common", 200 .offset = 0x180, 201 .bytes = 4, 202 .bit_offset = 0, 203 .nbits = 32, 204 }, { 205 .name = "tsensor-realignment", 206 .offset = 0x1fc, 207 .bytes = 4, 208 .bit_offset = 0, 209 .nbits = 32, 210 }, 211 }; 212 213 static const struct nvmem_cell_lookup tegra124_fuse_lookups[] = { 214 { 215 .nvmem_name = "fuse", 216 .cell_name = "xusb-pad-calibration", 217 .dev_id = "7009f000.padctl", 218 .con_id = "calibration", 219 }, { 220 .nvmem_name = "fuse", 221 .cell_name = "sata-calibration", 222 .dev_id = "70020000.sata", 223 .con_id = "calibration", 224 }, { 225 .nvmem_name = "fuse", 226 .cell_name = "tsensor-common", 227 .dev_id = "700e2000.thermal-sensor", 228 .con_id = "common", 229 }, { 230 .nvmem_name = "fuse", 231 .cell_name = "tsensor-realignment", 232 .dev_id = "700e2000.thermal-sensor", 233 .con_id = "realignment", 234 }, { 235 .nvmem_name = "fuse", 236 .cell_name = "tsensor-cpu0", 237 .dev_id = "700e2000.thermal-sensor", 238 .con_id = "cpu0", 239 }, { 240 .nvmem_name = "fuse", 241 .cell_name = "tsensor-cpu1", 242 .dev_id = "700e2000.thermal-sensor", 243 .con_id = "cpu1", 244 }, { 245 .nvmem_name = "fuse", 246 .cell_name = "tsensor-cpu2", 247 .dev_id = "700e2000.thermal-sensor", 248 .con_id = "cpu2", 249 }, { 250 .nvmem_name = "fuse", 251 .cell_name = "tsensor-cpu3", 252 .dev_id = "700e2000.thermal-sensor", 253 .con_id = "cpu3", 254 }, { 255 .nvmem_name = "fuse", 256 .cell_name = "tsensor-mem0", 257 .dev_id = "700e2000.thermal-sensor", 258 .con_id = "mem0", 259 }, { 260 .nvmem_name = "fuse", 261 .cell_name = "tsensor-mem1", 262 .dev_id = "700e2000.thermal-sensor", 263 .con_id = "mem1", 264 }, { 265 .nvmem_name = "fuse", 266 .cell_name = "tsensor-gpu", 267 .dev_id = "700e2000.thermal-sensor", 268 .con_id = "gpu", 269 }, { 270 .nvmem_name = "fuse", 271 .cell_name = "tsensor-pllx", 272 .dev_id = "700e2000.thermal-sensor", 273 .con_id = "pllx", 274 }, 275 }; 276 277 static const struct tegra_fuse_info tegra124_fuse_info = { 278 .read = tegra30_fuse_read, 279 .size = 0x300, 280 .spare = 0x200, 281 }; 282 283 const struct tegra_fuse_soc tegra124_fuse_soc = { 284 .init = tegra30_fuse_init, 285 .speedo_init = tegra124_init_speedo_data, 286 .info = &tegra124_fuse_info, 287 .lookups = tegra124_fuse_lookups, 288 .num_lookups = ARRAY_SIZE(tegra124_fuse_lookups), 289 .cells = tegra124_fuse_cells, 290 .num_cells = ARRAY_SIZE(tegra124_fuse_cells), 291 .soc_attr_group = &tegra_soc_attr_group, 292 .clk_suspend_on = true, 293 }; 294 #endif 295 296 #if defined(CONFIG_ARCH_TEGRA_210_SOC) 297 static const struct nvmem_cell_info tegra210_fuse_cells[] = { 298 { 299 .name = "tsensor-cpu1", 300 .offset = 0x084, 301 .bytes = 4, 302 .bit_offset = 0, 303 .nbits = 32, 304 }, { 305 .name = "tsensor-cpu2", 306 .offset = 0x088, 307 .bytes = 4, 308 .bit_offset = 0, 309 .nbits = 32, 310 }, { 311 .name = "tsensor-cpu0", 312 .offset = 0x098, 313 .bytes = 4, 314 .bit_offset = 0, 315 .nbits = 32, 316 }, { 317 .name = "xusb-pad-calibration", 318 .offset = 0x0f0, 319 .bytes = 4, 320 .bit_offset = 0, 321 .nbits = 32, 322 }, { 323 .name = "tsensor-cpu3", 324 .offset = 0x12c, 325 .bytes = 4, 326 .bit_offset = 0, 327 .nbits = 32, 328 }, { 329 .name = "sata-calibration", 330 .offset = 0x124, 331 .bytes = 4, 332 .bit_offset = 0, 333 .nbits = 32, 334 }, { 335 .name = "tsensor-gpu", 336 .offset = 0x154, 337 .bytes = 4, 338 .bit_offset = 0, 339 .nbits = 32, 340 }, { 341 .name = "tsensor-mem0", 342 .offset = 0x158, 343 .bytes = 4, 344 .bit_offset = 0, 345 .nbits = 32, 346 }, { 347 .name = "tsensor-mem1", 348 .offset = 0x15c, 349 .bytes = 4, 350 .bit_offset = 0, 351 .nbits = 32, 352 }, { 353 .name = "tsensor-pllx", 354 .offset = 0x160, 355 .bytes = 4, 356 .bit_offset = 0, 357 .nbits = 32, 358 }, { 359 .name = "tsensor-common", 360 .offset = 0x180, 361 .bytes = 4, 362 .bit_offset = 0, 363 .nbits = 32, 364 }, { 365 .name = "gpu-calibration", 366 .offset = 0x204, 367 .bytes = 4, 368 .bit_offset = 0, 369 .nbits = 32, 370 }, { 371 .name = "xusb-pad-calibration-ext", 372 .offset = 0x250, 373 .bytes = 4, 374 .bit_offset = 0, 375 .nbits = 32, 376 }, 377 }; 378 379 static const struct nvmem_cell_lookup tegra210_fuse_lookups[] = { 380 { 381 .nvmem_name = "fuse", 382 .cell_name = "tsensor-cpu1", 383 .dev_id = "700e2000.thermal-sensor", 384 .con_id = "cpu1", 385 }, { 386 .nvmem_name = "fuse", 387 .cell_name = "tsensor-cpu2", 388 .dev_id = "700e2000.thermal-sensor", 389 .con_id = "cpu2", 390 }, { 391 .nvmem_name = "fuse", 392 .cell_name = "tsensor-cpu0", 393 .dev_id = "700e2000.thermal-sensor", 394 .con_id = "cpu0", 395 }, { 396 .nvmem_name = "fuse", 397 .cell_name = "xusb-pad-calibration", 398 .dev_id = "7009f000.padctl", 399 .con_id = "calibration", 400 }, { 401 .nvmem_name = "fuse", 402 .cell_name = "tsensor-cpu3", 403 .dev_id = "700e2000.thermal-sensor", 404 .con_id = "cpu3", 405 }, { 406 .nvmem_name = "fuse", 407 .cell_name = "sata-calibration", 408 .dev_id = "70020000.sata", 409 .con_id = "calibration", 410 }, { 411 .nvmem_name = "fuse", 412 .cell_name = "tsensor-gpu", 413 .dev_id = "700e2000.thermal-sensor", 414 .con_id = "gpu", 415 }, { 416 .nvmem_name = "fuse", 417 .cell_name = "tsensor-mem0", 418 .dev_id = "700e2000.thermal-sensor", 419 .con_id = "mem0", 420 }, { 421 .nvmem_name = "fuse", 422 .cell_name = "tsensor-mem1", 423 .dev_id = "700e2000.thermal-sensor", 424 .con_id = "mem1", 425 }, { 426 .nvmem_name = "fuse", 427 .cell_name = "tsensor-pllx", 428 .dev_id = "700e2000.thermal-sensor", 429 .con_id = "pllx", 430 }, { 431 .nvmem_name = "fuse", 432 .cell_name = "tsensor-common", 433 .dev_id = "700e2000.thermal-sensor", 434 .con_id = "common", 435 }, { 436 .nvmem_name = "fuse", 437 .cell_name = "gpu-calibration", 438 .dev_id = "57000000.gpu", 439 .con_id = "calibration", 440 }, { 441 .nvmem_name = "fuse", 442 .cell_name = "xusb-pad-calibration-ext", 443 .dev_id = "7009f000.padctl", 444 .con_id = "calibration-ext", 445 }, 446 }; 447 448 static const struct tegra_fuse_info tegra210_fuse_info = { 449 .read = tegra30_fuse_read, 450 .size = 0x300, 451 .spare = 0x280, 452 }; 453 454 const struct tegra_fuse_soc tegra210_fuse_soc = { 455 .init = tegra30_fuse_init, 456 .speedo_init = tegra210_init_speedo_data, 457 .info = &tegra210_fuse_info, 458 .lookups = tegra210_fuse_lookups, 459 .cells = tegra210_fuse_cells, 460 .num_cells = ARRAY_SIZE(tegra210_fuse_cells), 461 .num_lookups = ARRAY_SIZE(tegra210_fuse_lookups), 462 .soc_attr_group = &tegra_soc_attr_group, 463 .clk_suspend_on = false, 464 }; 465 #endif 466 467 #if defined(CONFIG_ARCH_TEGRA_186_SOC) 468 static const struct nvmem_cell_info tegra186_fuse_cells[] = { 469 { 470 .name = "xusb-pad-calibration", 471 .offset = 0x0f0, 472 .bytes = 4, 473 .bit_offset = 0, 474 .nbits = 32, 475 }, { 476 .name = "xusb-pad-calibration-ext", 477 .offset = 0x250, 478 .bytes = 4, 479 .bit_offset = 0, 480 .nbits = 32, 481 }, 482 }; 483 484 static const struct nvmem_cell_lookup tegra186_fuse_lookups[] = { 485 { 486 .nvmem_name = "fuse", 487 .cell_name = "xusb-pad-calibration", 488 .dev_id = "3520000.padctl", 489 .con_id = "calibration", 490 }, { 491 .nvmem_name = "fuse", 492 .cell_name = "xusb-pad-calibration-ext", 493 .dev_id = "3520000.padctl", 494 .con_id = "calibration-ext", 495 }, 496 }; 497 498 static const struct nvmem_keepout tegra186_fuse_keepouts[] = { 499 { .start = 0x01c, .end = 0x0f0 }, 500 { .start = 0x138, .end = 0x198 }, 501 { .start = 0x1d8, .end = 0x250 }, 502 { .start = 0x280, .end = 0x290 }, 503 { .start = 0x340, .end = 0x344 } 504 }; 505 506 static const struct tegra_fuse_info tegra186_fuse_info = { 507 .read = tegra30_fuse_read, 508 .size = 0x478, 509 .spare = 0x280, 510 }; 511 512 const struct tegra_fuse_soc tegra186_fuse_soc = { 513 .init = tegra30_fuse_init, 514 .info = &tegra186_fuse_info, 515 .lookups = tegra186_fuse_lookups, 516 .num_lookups = ARRAY_SIZE(tegra186_fuse_lookups), 517 .cells = tegra186_fuse_cells, 518 .num_cells = ARRAY_SIZE(tegra186_fuse_cells), 519 .keepouts = tegra186_fuse_keepouts, 520 .num_keepouts = ARRAY_SIZE(tegra186_fuse_keepouts), 521 .soc_attr_group = &tegra_soc_attr_group, 522 .clk_suspend_on = false, 523 }; 524 #endif 525 526 #if defined(CONFIG_ARCH_TEGRA_194_SOC) 527 static const struct nvmem_cell_info tegra194_fuse_cells[] = { 528 { 529 .name = "xusb-pad-calibration", 530 .offset = 0x0f0, 531 .bytes = 4, 532 .bit_offset = 0, 533 .nbits = 32, 534 }, { 535 .name = "gpu-gcplex-config-fuse", 536 .offset = 0x1c8, 537 .bytes = 4, 538 .bit_offset = 0, 539 .nbits = 32, 540 }, { 541 .name = "xusb-pad-calibration-ext", 542 .offset = 0x250, 543 .bytes = 4, 544 .bit_offset = 0, 545 .nbits = 32, 546 }, { 547 .name = "gpu-pdi0", 548 .offset = 0x300, 549 .bytes = 4, 550 .bit_offset = 0, 551 .nbits = 32, 552 }, { 553 .name = "gpu-pdi1", 554 .offset = 0x304, 555 .bytes = 4, 556 .bit_offset = 0, 557 .nbits = 32, 558 }, 559 }; 560 561 static const struct nvmem_cell_lookup tegra194_fuse_lookups[] = { 562 { 563 .nvmem_name = "fuse", 564 .cell_name = "xusb-pad-calibration", 565 .dev_id = "3520000.padctl", 566 .con_id = "calibration", 567 }, { 568 .nvmem_name = "fuse", 569 .cell_name = "xusb-pad-calibration-ext", 570 .dev_id = "3520000.padctl", 571 .con_id = "calibration-ext", 572 }, { 573 .nvmem_name = "fuse", 574 .cell_name = "gpu-gcplex-config-fuse", 575 .dev_id = "17000000.gpu", 576 .con_id = "gcplex-config-fuse", 577 }, { 578 .nvmem_name = "fuse", 579 .cell_name = "gpu-pdi0", 580 .dev_id = "17000000.gpu", 581 .con_id = "pdi0", 582 }, { 583 .nvmem_name = "fuse", 584 .cell_name = "gpu-pdi1", 585 .dev_id = "17000000.gpu", 586 .con_id = "pdi1", 587 }, 588 }; 589 590 static const struct nvmem_keepout tegra194_fuse_keepouts[] = { 591 { .start = 0x01c, .end = 0x0b8 }, 592 { .start = 0x12c, .end = 0x198 }, 593 { .start = 0x1a0, .end = 0x1bc }, 594 { .start = 0x1d8, .end = 0x250 }, 595 { .start = 0x270, .end = 0x290 }, 596 { .start = 0x310, .end = 0x45c } 597 }; 598 599 static const struct tegra_fuse_info tegra194_fuse_info = { 600 .read = tegra30_fuse_read, 601 .size = 0x650, 602 .spare = 0x280, 603 }; 604 605 const struct tegra_fuse_soc tegra194_fuse_soc = { 606 .init = tegra30_fuse_init, 607 .info = &tegra194_fuse_info, 608 .lookups = tegra194_fuse_lookups, 609 .num_lookups = ARRAY_SIZE(tegra194_fuse_lookups), 610 .cells = tegra194_fuse_cells, 611 .num_cells = ARRAY_SIZE(tegra194_fuse_cells), 612 .keepouts = tegra194_fuse_keepouts, 613 .num_keepouts = ARRAY_SIZE(tegra194_fuse_keepouts), 614 .soc_attr_group = &tegra194_soc_attr_group, 615 .clk_suspend_on = false, 616 }; 617 #endif 618 619 #if defined(CONFIG_ARCH_TEGRA_234_SOC) 620 static const struct nvmem_cell_info tegra234_fuse_cells[] = { 621 { 622 .name = "xusb-pad-calibration", 623 .offset = 0x0f0, 624 .bytes = 4, 625 .bit_offset = 0, 626 .nbits = 32, 627 }, { 628 .name = "xusb-pad-calibration-ext", 629 .offset = 0x250, 630 .bytes = 4, 631 .bit_offset = 0, 632 .nbits = 32, 633 }, 634 }; 635 636 static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = { 637 { 638 .nvmem_name = "fuse", 639 .cell_name = "xusb-pad-calibration", 640 .dev_id = "3520000.padctl", 641 .con_id = "calibration", 642 }, { 643 .nvmem_name = "fuse", 644 .cell_name = "xusb-pad-calibration-ext", 645 .dev_id = "3520000.padctl", 646 .con_id = "calibration-ext", 647 }, 648 }; 649 650 static const struct nvmem_keepout tegra234_fuse_keepouts[] = { 651 { .start = 0x01c, .end = 0x0c8 }, 652 { .start = 0x12c, .end = 0x184 }, 653 { .start = 0x190, .end = 0x198 }, 654 { .start = 0x1a0, .end = 0x204 }, 655 { .start = 0x21c, .end = 0x250 }, 656 { .start = 0x25c, .end = 0x2f0 }, 657 { .start = 0x310, .end = 0x3d8 }, 658 { .start = 0x400, .end = 0x4f0 }, 659 { .start = 0x4f8, .end = 0x7e8 }, 660 { .start = 0x8d0, .end = 0x8d8 }, 661 { .start = 0xacc, .end = 0xf00 } 662 }; 663 664 static const struct tegra_fuse_info tegra234_fuse_info = { 665 .read = tegra30_fuse_read, 666 .size = 0xf90, 667 .spare = 0x280, 668 }; 669 670 const struct tegra_fuse_soc tegra234_fuse_soc = { 671 .init = tegra30_fuse_init, 672 .info = &tegra234_fuse_info, 673 .lookups = tegra234_fuse_lookups, 674 .num_lookups = ARRAY_SIZE(tegra234_fuse_lookups), 675 .cells = tegra234_fuse_cells, 676 .num_cells = ARRAY_SIZE(tegra234_fuse_cells), 677 .keepouts = tegra234_fuse_keepouts, 678 .num_keepouts = ARRAY_SIZE(tegra234_fuse_keepouts), 679 .soc_attr_group = &tegra194_soc_attr_group, 680 .clk_suspend_on = false, 681 }; 682 #endif 683