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