1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved. 4 */ 5 6 #include <linux/of.h> 7 #include <linux/of_device.h> 8 #include <linux/slab.h> 9 10 #include <dt-bindings/memory/tegra30-mc.h> 11 12 #include "mc.h" 13 14 static const unsigned long tegra30_mc_emem_regs[] = { 15 MC_EMEM_ARB_CFG, 16 MC_EMEM_ARB_OUTSTANDING_REQ, 17 MC_EMEM_ARB_TIMING_RCD, 18 MC_EMEM_ARB_TIMING_RP, 19 MC_EMEM_ARB_TIMING_RC, 20 MC_EMEM_ARB_TIMING_RAS, 21 MC_EMEM_ARB_TIMING_FAW, 22 MC_EMEM_ARB_TIMING_RRD, 23 MC_EMEM_ARB_TIMING_RAP2PRE, 24 MC_EMEM_ARB_TIMING_WAP2PRE, 25 MC_EMEM_ARB_TIMING_R2R, 26 MC_EMEM_ARB_TIMING_W2W, 27 MC_EMEM_ARB_TIMING_R2W, 28 MC_EMEM_ARB_TIMING_W2R, 29 MC_EMEM_ARB_DA_TURNS, 30 MC_EMEM_ARB_DA_COVERS, 31 MC_EMEM_ARB_MISC0, 32 MC_EMEM_ARB_RING1_THROTTLE, 33 }; 34 35 static const struct tegra_mc_client tegra30_mc_clients[] = { 36 { 37 .id = 0x00, 38 .name = "ptcr", 39 .swgroup = TEGRA_SWGROUP_PTC, 40 .la = { 41 .reg = 0x34c, 42 .shift = 0, 43 .mask = 0xff, 44 .def = 0x0, 45 }, 46 .fifo_size = 16 * 2, 47 }, { 48 .id = 0x01, 49 .name = "display0a", 50 .swgroup = TEGRA_SWGROUP_DC, 51 .smmu = { 52 .reg = 0x228, 53 .bit = 1, 54 }, 55 .la = { 56 .reg = 0x2e8, 57 .shift = 0, 58 .mask = 0xff, 59 .def = 0x4e, 60 }, 61 .fifo_size = 16 * 128, 62 }, { 63 .id = 0x02, 64 .name = "display0ab", 65 .swgroup = TEGRA_SWGROUP_DCB, 66 .smmu = { 67 .reg = 0x228, 68 .bit = 2, 69 }, 70 .la = { 71 .reg = 0x2f4, 72 .shift = 0, 73 .mask = 0xff, 74 .def = 0x4e, 75 }, 76 .fifo_size = 16 * 128, 77 }, { 78 .id = 0x03, 79 .name = "display0b", 80 .swgroup = TEGRA_SWGROUP_DC, 81 .smmu = { 82 .reg = 0x228, 83 .bit = 3, 84 }, 85 .la = { 86 .reg = 0x2e8, 87 .shift = 16, 88 .mask = 0xff, 89 .def = 0x4e, 90 }, 91 .fifo_size = 16 * 64, 92 }, { 93 .id = 0x04, 94 .name = "display0bb", 95 .swgroup = TEGRA_SWGROUP_DCB, 96 .smmu = { 97 .reg = 0x228, 98 .bit = 4, 99 }, 100 .la = { 101 .reg = 0x2f4, 102 .shift = 16, 103 .mask = 0xff, 104 .def = 0x4e, 105 }, 106 .fifo_size = 16 * 64, 107 }, { 108 .id = 0x05, 109 .name = "display0c", 110 .swgroup = TEGRA_SWGROUP_DC, 111 .smmu = { 112 .reg = 0x228, 113 .bit = 5, 114 }, 115 .la = { 116 .reg = 0x2ec, 117 .shift = 0, 118 .mask = 0xff, 119 .def = 0x4e, 120 }, 121 .fifo_size = 16 * 128, 122 }, { 123 .id = 0x06, 124 .name = "display0cb", 125 .swgroup = TEGRA_SWGROUP_DCB, 126 .smmu = { 127 .reg = 0x228, 128 .bit = 6, 129 }, 130 .la = { 131 .reg = 0x2f8, 132 .shift = 0, 133 .mask = 0xff, 134 .def = 0x4e, 135 }, 136 .fifo_size = 16 * 128, 137 }, { 138 .id = 0x07, 139 .name = "display1b", 140 .swgroup = TEGRA_SWGROUP_DC, 141 .smmu = { 142 .reg = 0x228, 143 .bit = 7, 144 }, 145 .la = { 146 .reg = 0x2ec, 147 .shift = 16, 148 .mask = 0xff, 149 .def = 0x4e, 150 }, 151 .fifo_size = 16 * 64, 152 }, { 153 .id = 0x08, 154 .name = "display1bb", 155 .swgroup = TEGRA_SWGROUP_DCB, 156 .smmu = { 157 .reg = 0x228, 158 .bit = 8, 159 }, 160 .la = { 161 .reg = 0x2f8, 162 .shift = 16, 163 .mask = 0xff, 164 .def = 0x4e, 165 }, 166 .fifo_size = 16 * 64, 167 }, { 168 .id = 0x09, 169 .name = "eppup", 170 .swgroup = TEGRA_SWGROUP_EPP, 171 .smmu = { 172 .reg = 0x228, 173 .bit = 9, 174 }, 175 .la = { 176 .reg = 0x300, 177 .shift = 0, 178 .mask = 0xff, 179 .def = 0x17, 180 }, 181 .fifo_size = 16 * 8, 182 }, { 183 .id = 0x0a, 184 .name = "g2pr", 185 .swgroup = TEGRA_SWGROUP_G2, 186 .smmu = { 187 .reg = 0x228, 188 .bit = 10, 189 }, 190 .la = { 191 .reg = 0x308, 192 .shift = 0, 193 .mask = 0xff, 194 .def = 0x09, 195 }, 196 .fifo_size = 16 * 64, 197 }, { 198 .id = 0x0b, 199 .name = "g2sr", 200 .swgroup = TEGRA_SWGROUP_G2, 201 .smmu = { 202 .reg = 0x228, 203 .bit = 11, 204 }, 205 .la = { 206 .reg = 0x308, 207 .shift = 16, 208 .mask = 0xff, 209 .def = 0x09, 210 }, 211 .fifo_size = 16 * 64, 212 }, { 213 .id = 0x0c, 214 .name = "mpeunifbr", 215 .swgroup = TEGRA_SWGROUP_MPE, 216 .smmu = { 217 .reg = 0x228, 218 .bit = 12, 219 }, 220 .la = { 221 .reg = 0x328, 222 .shift = 0, 223 .mask = 0xff, 224 .def = 0x50, 225 }, 226 .fifo_size = 16 * 8, 227 }, { 228 .id = 0x0d, 229 .name = "viruv", 230 .swgroup = TEGRA_SWGROUP_VI, 231 .smmu = { 232 .reg = 0x228, 233 .bit = 13, 234 }, 235 .la = { 236 .reg = 0x364, 237 .shift = 0, 238 .mask = 0xff, 239 .def = 0x2c, 240 }, 241 .fifo_size = 16 * 8, 242 }, { 243 .id = 0x0e, 244 .name = "afir", 245 .swgroup = TEGRA_SWGROUP_AFI, 246 .smmu = { 247 .reg = 0x228, 248 .bit = 14, 249 }, 250 .la = { 251 .reg = 0x2e0, 252 .shift = 0, 253 .mask = 0xff, 254 .def = 0x10, 255 }, 256 .fifo_size = 16 * 32, 257 }, { 258 .id = 0x0f, 259 .name = "avpcarm7r", 260 .swgroup = TEGRA_SWGROUP_AVPC, 261 .smmu = { 262 .reg = 0x228, 263 .bit = 15, 264 }, 265 .la = { 266 .reg = 0x2e4, 267 .shift = 0, 268 .mask = 0xff, 269 .def = 0x04, 270 }, 271 .fifo_size = 16 * 2, 272 }, { 273 .id = 0x10, 274 .name = "displayhc", 275 .swgroup = TEGRA_SWGROUP_DC, 276 .smmu = { 277 .reg = 0x228, 278 .bit = 16, 279 }, 280 .la = { 281 .reg = 0x2f0, 282 .shift = 0, 283 .mask = 0xff, 284 .def = 0xff, 285 }, 286 .fifo_size = 16 * 2, 287 }, { 288 .id = 0x11, 289 .name = "displayhcb", 290 .swgroup = TEGRA_SWGROUP_DCB, 291 .smmu = { 292 .reg = 0x228, 293 .bit = 17, 294 }, 295 .la = { 296 .reg = 0x2fc, 297 .shift = 0, 298 .mask = 0xff, 299 .def = 0xff, 300 }, 301 .fifo_size = 16 * 2, 302 }, { 303 .id = 0x12, 304 .name = "fdcdrd", 305 .swgroup = TEGRA_SWGROUP_NV, 306 .smmu = { 307 .reg = 0x228, 308 .bit = 18, 309 }, 310 .la = { 311 .reg = 0x334, 312 .shift = 0, 313 .mask = 0xff, 314 .def = 0x0a, 315 }, 316 .fifo_size = 16 * 48, 317 }, { 318 .id = 0x13, 319 .name = "fdcdrd2", 320 .swgroup = TEGRA_SWGROUP_NV2, 321 .smmu = { 322 .reg = 0x228, 323 .bit = 19, 324 }, 325 .la = { 326 .reg = 0x33c, 327 .shift = 0, 328 .mask = 0xff, 329 .def = 0x0a, 330 }, 331 .fifo_size = 16 * 48, 332 }, { 333 .id = 0x14, 334 .name = "g2dr", 335 .swgroup = TEGRA_SWGROUP_G2, 336 .smmu = { 337 .reg = 0x228, 338 .bit = 20, 339 }, 340 .la = { 341 .reg = 0x30c, 342 .shift = 0, 343 .mask = 0xff, 344 .def = 0x0a, 345 }, 346 .fifo_size = 16 * 48, 347 }, { 348 .id = 0x15, 349 .name = "hdar", 350 .swgroup = TEGRA_SWGROUP_HDA, 351 .smmu = { 352 .reg = 0x228, 353 .bit = 21, 354 }, 355 .la = { 356 .reg = 0x318, 357 .shift = 0, 358 .mask = 0xff, 359 .def = 0xff, 360 }, 361 .fifo_size = 16 * 16, 362 }, { 363 .id = 0x16, 364 .name = "host1xdmar", 365 .swgroup = TEGRA_SWGROUP_HC, 366 .smmu = { 367 .reg = 0x228, 368 .bit = 22, 369 }, 370 .la = { 371 .reg = 0x310, 372 .shift = 0, 373 .mask = 0xff, 374 .def = 0x05, 375 }, 376 .fifo_size = 16 * 16, 377 }, { 378 .id = 0x17, 379 .name = "host1xr", 380 .swgroup = TEGRA_SWGROUP_HC, 381 .smmu = { 382 .reg = 0x228, 383 .bit = 23, 384 }, 385 .la = { 386 .reg = 0x310, 387 .shift = 16, 388 .mask = 0xff, 389 .def = 0x50, 390 }, 391 .fifo_size = 16 * 8, 392 }, { 393 .id = 0x18, 394 .name = "idxsrd", 395 .swgroup = TEGRA_SWGROUP_NV, 396 .smmu = { 397 .reg = 0x228, 398 .bit = 24, 399 }, 400 .la = { 401 .reg = 0x334, 402 .shift = 16, 403 .mask = 0xff, 404 .def = 0x13, 405 }, 406 .fifo_size = 16 * 64, 407 }, { 408 .id = 0x19, 409 .name = "idxsrd2", 410 .swgroup = TEGRA_SWGROUP_NV2, 411 .smmu = { 412 .reg = 0x228, 413 .bit = 25, 414 }, 415 .la = { 416 .reg = 0x33c, 417 .shift = 16, 418 .mask = 0xff, 419 .def = 0x13, 420 }, 421 .fifo_size = 16 * 64, 422 }, { 423 .id = 0x1a, 424 .name = "mpe_ipred", 425 .swgroup = TEGRA_SWGROUP_MPE, 426 .smmu = { 427 .reg = 0x228, 428 .bit = 26, 429 }, 430 .la = { 431 .reg = 0x328, 432 .shift = 16, 433 .mask = 0xff, 434 .def = 0x80, 435 }, 436 .fifo_size = 16 * 2, 437 }, { 438 .id = 0x1b, 439 .name = "mpeamemrd", 440 .swgroup = TEGRA_SWGROUP_MPE, 441 .smmu = { 442 .reg = 0x228, 443 .bit = 27, 444 }, 445 .la = { 446 .reg = 0x32c, 447 .shift = 0, 448 .mask = 0xff, 449 .def = 0x42, 450 }, 451 .fifo_size = 16 * 64, 452 }, { 453 .id = 0x1c, 454 .name = "mpecsrd", 455 .swgroup = TEGRA_SWGROUP_MPE, 456 .smmu = { 457 .reg = 0x228, 458 .bit = 28, 459 }, 460 .la = { 461 .reg = 0x32c, 462 .shift = 16, 463 .mask = 0xff, 464 .def = 0xff, 465 }, 466 .fifo_size = 16 * 8, 467 }, { 468 .id = 0x1d, 469 .name = "ppcsahbdmar", 470 .swgroup = TEGRA_SWGROUP_PPCS, 471 .smmu = { 472 .reg = 0x228, 473 .bit = 29, 474 }, 475 .la = { 476 .reg = 0x344, 477 .shift = 0, 478 .mask = 0xff, 479 .def = 0x10, 480 }, 481 .fifo_size = 16 * 2, 482 }, { 483 .id = 0x1e, 484 .name = "ppcsahbslvr", 485 .swgroup = TEGRA_SWGROUP_PPCS, 486 .smmu = { 487 .reg = 0x228, 488 .bit = 30, 489 }, 490 .la = { 491 .reg = 0x344, 492 .shift = 16, 493 .mask = 0xff, 494 .def = 0x12, 495 }, 496 .fifo_size = 16 * 8, 497 }, { 498 .id = 0x1f, 499 .name = "satar", 500 .swgroup = TEGRA_SWGROUP_SATA, 501 .smmu = { 502 .reg = 0x228, 503 .bit = 31, 504 }, 505 .la = { 506 .reg = 0x350, 507 .shift = 0, 508 .mask = 0xff, 509 .def = 0x33, 510 }, 511 .fifo_size = 16 * 32, 512 }, { 513 .id = 0x20, 514 .name = "texsrd", 515 .swgroup = TEGRA_SWGROUP_NV, 516 .smmu = { 517 .reg = 0x22c, 518 .bit = 0, 519 }, 520 .la = { 521 .reg = 0x338, 522 .shift = 0, 523 .mask = 0xff, 524 .def = 0x13, 525 }, 526 .fifo_size = 16 * 64, 527 }, { 528 .id = 0x21, 529 .name = "texsrd2", 530 .swgroup = TEGRA_SWGROUP_NV2, 531 .smmu = { 532 .reg = 0x22c, 533 .bit = 1, 534 }, 535 .la = { 536 .reg = 0x340, 537 .shift = 0, 538 .mask = 0xff, 539 .def = 0x13, 540 }, 541 .fifo_size = 16 * 64, 542 }, { 543 .id = 0x22, 544 .name = "vdebsevr", 545 .swgroup = TEGRA_SWGROUP_VDE, 546 .smmu = { 547 .reg = 0x22c, 548 .bit = 2, 549 }, 550 .la = { 551 .reg = 0x354, 552 .shift = 0, 553 .mask = 0xff, 554 .def = 0xff, 555 }, 556 .fifo_size = 16 * 8, 557 }, { 558 .id = 0x23, 559 .name = "vdember", 560 .swgroup = TEGRA_SWGROUP_VDE, 561 .smmu = { 562 .reg = 0x22c, 563 .bit = 3, 564 }, 565 .la = { 566 .reg = 0x354, 567 .shift = 16, 568 .mask = 0xff, 569 .def = 0xd0, 570 }, 571 .fifo_size = 16 * 4, 572 }, { 573 .id = 0x24, 574 .name = "vdemcer", 575 .swgroup = TEGRA_SWGROUP_VDE, 576 .smmu = { 577 .reg = 0x22c, 578 .bit = 4, 579 }, 580 .la = { 581 .reg = 0x358, 582 .shift = 0, 583 .mask = 0xff, 584 .def = 0x2a, 585 }, 586 .fifo_size = 16 * 16, 587 }, { 588 .id = 0x25, 589 .name = "vdetper", 590 .swgroup = TEGRA_SWGROUP_VDE, 591 .smmu = { 592 .reg = 0x22c, 593 .bit = 5, 594 }, 595 .la = { 596 .reg = 0x358, 597 .shift = 16, 598 .mask = 0xff, 599 .def = 0x74, 600 }, 601 .fifo_size = 16 * 16, 602 }, { 603 .id = 0x26, 604 .name = "mpcorelpr", 605 .swgroup = TEGRA_SWGROUP_MPCORELP, 606 .la = { 607 .reg = 0x324, 608 .shift = 0, 609 .mask = 0xff, 610 .def = 0x04, 611 }, 612 .fifo_size = 16 * 14, 613 }, { 614 .id = 0x27, 615 .name = "mpcorer", 616 .swgroup = TEGRA_SWGROUP_MPCORE, 617 .la = { 618 .reg = 0x320, 619 .shift = 0, 620 .mask = 0xff, 621 .def = 0x04, 622 }, 623 .fifo_size = 16 * 14, 624 }, { 625 .id = 0x28, 626 .name = "eppu", 627 .swgroup = TEGRA_SWGROUP_EPP, 628 .smmu = { 629 .reg = 0x22c, 630 .bit = 8, 631 }, 632 .la = { 633 .reg = 0x300, 634 .shift = 16, 635 .mask = 0xff, 636 .def = 0x6c, 637 }, 638 .fifo_size = 16 * 64, 639 }, { 640 .id = 0x29, 641 .name = "eppv", 642 .swgroup = TEGRA_SWGROUP_EPP, 643 .smmu = { 644 .reg = 0x22c, 645 .bit = 9, 646 }, 647 .la = { 648 .reg = 0x304, 649 .shift = 0, 650 .mask = 0xff, 651 .def = 0x6c, 652 }, 653 .fifo_size = 16 * 64, 654 }, { 655 .id = 0x2a, 656 .name = "eppy", 657 .swgroup = TEGRA_SWGROUP_EPP, 658 .smmu = { 659 .reg = 0x22c, 660 .bit = 10, 661 }, 662 .la = { 663 .reg = 0x304, 664 .shift = 16, 665 .mask = 0xff, 666 .def = 0x6c, 667 }, 668 .fifo_size = 16 * 64, 669 }, { 670 .id = 0x2b, 671 .name = "mpeunifbw", 672 .swgroup = TEGRA_SWGROUP_MPE, 673 .smmu = { 674 .reg = 0x22c, 675 .bit = 11, 676 }, 677 .la = { 678 .reg = 0x330, 679 .shift = 0, 680 .mask = 0xff, 681 .def = 0x13, 682 }, 683 .fifo_size = 16 * 8, 684 }, { 685 .id = 0x2c, 686 .name = "viwsb", 687 .swgroup = TEGRA_SWGROUP_VI, 688 .smmu = { 689 .reg = 0x22c, 690 .bit = 12, 691 }, 692 .la = { 693 .reg = 0x364, 694 .shift = 16, 695 .mask = 0xff, 696 .def = 0x12, 697 }, 698 .fifo_size = 16 * 64, 699 }, { 700 .id = 0x2d, 701 .name = "viwu", 702 .swgroup = TEGRA_SWGROUP_VI, 703 .smmu = { 704 .reg = 0x22c, 705 .bit = 13, 706 }, 707 .la = { 708 .reg = 0x368, 709 .shift = 0, 710 .mask = 0xff, 711 .def = 0xb2, 712 }, 713 .fifo_size = 16 * 64, 714 }, { 715 .id = 0x2e, 716 .name = "viwv", 717 .swgroup = TEGRA_SWGROUP_VI, 718 .smmu = { 719 .reg = 0x22c, 720 .bit = 14, 721 }, 722 .la = { 723 .reg = 0x368, 724 .shift = 16, 725 .mask = 0xff, 726 .def = 0xb2, 727 }, 728 .fifo_size = 16 * 64, 729 }, { 730 .id = 0x2f, 731 .name = "viwy", 732 .swgroup = TEGRA_SWGROUP_VI, 733 .smmu = { 734 .reg = 0x22c, 735 .bit = 15, 736 }, 737 .la = { 738 .reg = 0x36c, 739 .shift = 0, 740 .mask = 0xff, 741 .def = 0x12, 742 }, 743 .fifo_size = 16 * 64, 744 }, { 745 .id = 0x30, 746 .name = "g2dw", 747 .swgroup = TEGRA_SWGROUP_G2, 748 .smmu = { 749 .reg = 0x22c, 750 .bit = 16, 751 }, 752 .la = { 753 .reg = 0x30c, 754 .shift = 16, 755 .mask = 0xff, 756 .def = 0x9, 757 }, 758 .fifo_size = 16 * 128, 759 }, { 760 .id = 0x31, 761 .name = "afiw", 762 .swgroup = TEGRA_SWGROUP_AFI, 763 .smmu = { 764 .reg = 0x22c, 765 .bit = 17, 766 }, 767 .la = { 768 .reg = 0x2e0, 769 .shift = 16, 770 .mask = 0xff, 771 .def = 0x0c, 772 }, 773 .fifo_size = 16 * 32, 774 }, { 775 .id = 0x32, 776 .name = "avpcarm7w", 777 .swgroup = TEGRA_SWGROUP_AVPC, 778 .smmu = { 779 .reg = 0x22c, 780 .bit = 18, 781 }, 782 .la = { 783 .reg = 0x2e4, 784 .shift = 16, 785 .mask = 0xff, 786 .def = 0x0e, 787 }, 788 .fifo_size = 16 * 2, 789 }, { 790 .id = 0x33, 791 .name = "fdcdwr", 792 .swgroup = TEGRA_SWGROUP_NV, 793 .smmu = { 794 .reg = 0x22c, 795 .bit = 19, 796 }, 797 .la = { 798 .reg = 0x338, 799 .shift = 16, 800 .mask = 0xff, 801 .def = 0x0a, 802 }, 803 .fifo_size = 16 * 48, 804 }, { 805 .id = 0x34, 806 .name = "fdcdwr2", 807 .swgroup = TEGRA_SWGROUP_NV2, 808 .smmu = { 809 .reg = 0x22c, 810 .bit = 20, 811 }, 812 .la = { 813 .reg = 0x340, 814 .shift = 16, 815 .mask = 0xff, 816 .def = 0x0a, 817 }, 818 .fifo_size = 16 * 48, 819 }, { 820 .id = 0x35, 821 .name = "hdaw", 822 .swgroup = TEGRA_SWGROUP_HDA, 823 .smmu = { 824 .reg = 0x22c, 825 .bit = 21, 826 }, 827 .la = { 828 .reg = 0x318, 829 .shift = 16, 830 .mask = 0xff, 831 .def = 0xff, 832 }, 833 .fifo_size = 16 * 16, 834 }, { 835 .id = 0x36, 836 .name = "host1xw", 837 .swgroup = TEGRA_SWGROUP_HC, 838 .smmu = { 839 .reg = 0x22c, 840 .bit = 22, 841 }, 842 .la = { 843 .reg = 0x314, 844 .shift = 0, 845 .mask = 0xff, 846 .def = 0x10, 847 }, 848 .fifo_size = 16 * 32, 849 }, { 850 .id = 0x37, 851 .name = "ispw", 852 .swgroup = TEGRA_SWGROUP_ISP, 853 .smmu = { 854 .reg = 0x22c, 855 .bit = 23, 856 }, 857 .la = { 858 .reg = 0x31c, 859 .shift = 0, 860 .mask = 0xff, 861 .def = 0xff, 862 }, 863 .fifo_size = 16 * 64, 864 }, { 865 .id = 0x38, 866 .name = "mpcorelpw", 867 .swgroup = TEGRA_SWGROUP_MPCORELP, 868 .la = { 869 .reg = 0x324, 870 .shift = 16, 871 .mask = 0xff, 872 .def = 0x0e, 873 }, 874 .fifo_size = 16 * 24, 875 }, { 876 .id = 0x39, 877 .name = "mpcorew", 878 .swgroup = TEGRA_SWGROUP_MPCORE, 879 .la = { 880 .reg = 0x320, 881 .shift = 16, 882 .mask = 0xff, 883 .def = 0x0e, 884 }, 885 .fifo_size = 16 * 24, 886 }, { 887 .id = 0x3a, 888 .name = "mpecswr", 889 .swgroup = TEGRA_SWGROUP_MPE, 890 .smmu = { 891 .reg = 0x22c, 892 .bit = 26, 893 }, 894 .la = { 895 .reg = 0x330, 896 .shift = 16, 897 .mask = 0xff, 898 .def = 0xff, 899 }, 900 .fifo_size = 16 * 8, 901 }, { 902 .id = 0x3b, 903 .name = "ppcsahbdmaw", 904 .swgroup = TEGRA_SWGROUP_PPCS, 905 .smmu = { 906 .reg = 0x22c, 907 .bit = 27, 908 }, 909 .la = { 910 .reg = 0x348, 911 .shift = 0, 912 .mask = 0xff, 913 .def = 0x10, 914 }, 915 .fifo_size = 16 * 2, 916 }, { 917 .id = 0x3c, 918 .name = "ppcsahbslvw", 919 .swgroup = TEGRA_SWGROUP_PPCS, 920 .smmu = { 921 .reg = 0x22c, 922 .bit = 28, 923 }, 924 .la = { 925 .reg = 0x348, 926 .shift = 16, 927 .mask = 0xff, 928 .def = 0x06, 929 }, 930 .fifo_size = 16 * 4, 931 }, { 932 .id = 0x3d, 933 .name = "sataw", 934 .swgroup = TEGRA_SWGROUP_SATA, 935 .smmu = { 936 .reg = 0x22c, 937 .bit = 29, 938 }, 939 .la = { 940 .reg = 0x350, 941 .shift = 16, 942 .mask = 0xff, 943 .def = 0x33, 944 }, 945 .fifo_size = 16 * 32, 946 }, { 947 .id = 0x3e, 948 .name = "vdebsevw", 949 .swgroup = TEGRA_SWGROUP_VDE, 950 .smmu = { 951 .reg = 0x22c, 952 .bit = 30, 953 }, 954 .la = { 955 .reg = 0x35c, 956 .shift = 0, 957 .mask = 0xff, 958 .def = 0xff, 959 }, 960 .fifo_size = 16 * 4, 961 }, { 962 .id = 0x3f, 963 .name = "vdedbgw", 964 .swgroup = TEGRA_SWGROUP_VDE, 965 .smmu = { 966 .reg = 0x22c, 967 .bit = 31, 968 }, 969 .la = { 970 .reg = 0x35c, 971 .shift = 16, 972 .mask = 0xff, 973 .def = 0xff, 974 }, 975 .fifo_size = 16 * 16, 976 }, { 977 .id = 0x40, 978 .name = "vdembew", 979 .swgroup = TEGRA_SWGROUP_VDE, 980 .smmu = { 981 .reg = 0x230, 982 .bit = 0, 983 }, 984 .la = { 985 .reg = 0x360, 986 .shift = 0, 987 .mask = 0xff, 988 .def = 0x42, 989 }, 990 .fifo_size = 16 * 2, 991 }, { 992 .id = 0x41, 993 .name = "vdetpmw", 994 .swgroup = TEGRA_SWGROUP_VDE, 995 .smmu = { 996 .reg = 0x230, 997 .bit = 1, 998 }, 999 .la = { 1000 .reg = 0x360, 1001 .shift = 16, 1002 .mask = 0xff, 1003 .def = 0x2a, 1004 }, 1005 .fifo_size = 16 * 16, 1006 }, 1007 }; 1008 1009 static const struct tegra_smmu_swgroup tegra30_swgroups[] = { 1010 { .name = "dc", .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 }, 1011 { .name = "dcb", .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 }, 1012 { .name = "epp", .swgroup = TEGRA_SWGROUP_EPP, .reg = 0x248 }, 1013 { .name = "g2", .swgroup = TEGRA_SWGROUP_G2, .reg = 0x24c }, 1014 { .name = "mpe", .swgroup = TEGRA_SWGROUP_MPE, .reg = 0x264 }, 1015 { .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, 1016 { .name = "afi", .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 }, 1017 { .name = "avpc", .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c }, 1018 { .name = "nv", .swgroup = TEGRA_SWGROUP_NV, .reg = 0x268 }, 1019 { .name = "nv2", .swgroup = TEGRA_SWGROUP_NV2, .reg = 0x26c }, 1020 { .name = "hda", .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 }, 1021 { .name = "hc", .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 }, 1022 { .name = "ppcs", .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 }, 1023 { .name = "sata", .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x278 }, 1024 { .name = "vde", .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c }, 1025 { .name = "isp", .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 }, 1026 }; 1027 1028 static const unsigned int tegra30_group_drm[] = { 1029 TEGRA_SWGROUP_DC, 1030 TEGRA_SWGROUP_DCB, 1031 TEGRA_SWGROUP_G2, 1032 TEGRA_SWGROUP_NV, 1033 TEGRA_SWGROUP_NV2, 1034 }; 1035 1036 static const struct tegra_smmu_group_soc tegra30_groups[] = { 1037 { 1038 .name = "drm", 1039 .swgroups = tegra30_group_drm, 1040 .num_swgroups = ARRAY_SIZE(tegra30_group_drm), 1041 }, 1042 }; 1043 1044 static const struct tegra_smmu_soc tegra30_smmu_soc = { 1045 .clients = tegra30_mc_clients, 1046 .num_clients = ARRAY_SIZE(tegra30_mc_clients), 1047 .swgroups = tegra30_swgroups, 1048 .num_swgroups = ARRAY_SIZE(tegra30_swgroups), 1049 .groups = tegra30_groups, 1050 .num_groups = ARRAY_SIZE(tegra30_groups), 1051 .supports_round_robin_arbitration = false, 1052 .supports_request_limit = false, 1053 .num_tlb_lines = 16, 1054 .num_asids = 4, 1055 }; 1056 1057 #define TEGRA30_MC_RESET(_name, _control, _status, _bit) \ 1058 { \ 1059 .name = #_name, \ 1060 .id = TEGRA30_MC_RESET_##_name, \ 1061 .control = _control, \ 1062 .status = _status, \ 1063 .bit = _bit, \ 1064 } 1065 1066 static const struct tegra_mc_reset tegra30_mc_resets[] = { 1067 TEGRA30_MC_RESET(AFI, 0x200, 0x204, 0), 1068 TEGRA30_MC_RESET(AVPC, 0x200, 0x204, 1), 1069 TEGRA30_MC_RESET(DC, 0x200, 0x204, 2), 1070 TEGRA30_MC_RESET(DCB, 0x200, 0x204, 3), 1071 TEGRA30_MC_RESET(EPP, 0x200, 0x204, 4), 1072 TEGRA30_MC_RESET(2D, 0x200, 0x204, 5), 1073 TEGRA30_MC_RESET(HC, 0x200, 0x204, 6), 1074 TEGRA30_MC_RESET(HDA, 0x200, 0x204, 7), 1075 TEGRA30_MC_RESET(ISP, 0x200, 0x204, 8), 1076 TEGRA30_MC_RESET(MPCORE, 0x200, 0x204, 9), 1077 TEGRA30_MC_RESET(MPCORELP, 0x200, 0x204, 10), 1078 TEGRA30_MC_RESET(MPE, 0x200, 0x204, 11), 1079 TEGRA30_MC_RESET(3D, 0x200, 0x204, 12), 1080 TEGRA30_MC_RESET(3D2, 0x200, 0x204, 13), 1081 TEGRA30_MC_RESET(PPCS, 0x200, 0x204, 14), 1082 TEGRA30_MC_RESET(SATA, 0x200, 0x204, 15), 1083 TEGRA30_MC_RESET(VDE, 0x200, 0x204, 16), 1084 TEGRA30_MC_RESET(VI, 0x200, 0x204, 17), 1085 }; 1086 1087 static void tegra30_mc_tune_client_latency(struct tegra_mc *mc, 1088 const struct tegra_mc_client *client, 1089 unsigned int bandwidth_mbytes_sec) 1090 { 1091 u32 arb_tolerance_compensation_nsec, arb_tolerance_compensation_div; 1092 const struct tegra_mc_la *la = &client->la; 1093 unsigned int fifo_size = client->fifo_size; 1094 u32 arb_nsec, la_ticks, value; 1095 1096 /* see 18.4.1 Client Configuration in Tegra3 TRM v03p */ 1097 if (bandwidth_mbytes_sec) 1098 arb_nsec = fifo_size * NSEC_PER_USEC / bandwidth_mbytes_sec; 1099 else 1100 arb_nsec = U32_MAX; 1101 1102 /* 1103 * Latency allowness should be set with consideration for the module's 1104 * latency tolerance and internal buffering capabilities. 1105 * 1106 * Display memory clients use isochronous transfers and have very low 1107 * tolerance to a belated transfers. Hence we need to compensate the 1108 * memory arbitration imperfection for them in order to prevent FIFO 1109 * underflow condition when memory bus is busy. 1110 * 1111 * VI clients also need a stronger compensation. 1112 */ 1113 switch (client->swgroup) { 1114 case TEGRA_SWGROUP_MPCORE: 1115 case TEGRA_SWGROUP_PTC: 1116 /* 1117 * We always want lower latency for these clients, hence 1118 * don't touch them. 1119 */ 1120 return; 1121 1122 case TEGRA_SWGROUP_DC: 1123 case TEGRA_SWGROUP_DCB: 1124 arb_tolerance_compensation_nsec = 1050; 1125 arb_tolerance_compensation_div = 2; 1126 break; 1127 1128 case TEGRA_SWGROUP_VI: 1129 arb_tolerance_compensation_nsec = 1050; 1130 arb_tolerance_compensation_div = 1; 1131 break; 1132 1133 default: 1134 arb_tolerance_compensation_nsec = 150; 1135 arb_tolerance_compensation_div = 1; 1136 break; 1137 } 1138 1139 if (arb_nsec > arb_tolerance_compensation_nsec) 1140 arb_nsec -= arb_tolerance_compensation_nsec; 1141 else 1142 arb_nsec = 0; 1143 1144 arb_nsec /= arb_tolerance_compensation_div; 1145 1146 /* 1147 * Latency allowance is a number of ticks a request from a particular 1148 * client may wait in the EMEM arbiter before it becomes a high-priority 1149 * request. 1150 */ 1151 la_ticks = arb_nsec / mc->tick; 1152 la_ticks = min(la_ticks, la->mask); 1153 1154 value = mc_readl(mc, la->reg); 1155 value &= ~(la->mask << la->shift); 1156 value |= la_ticks << la->shift; 1157 mc_writel(mc, value, la->reg); 1158 } 1159 1160 static int tegra30_mc_icc_set(struct icc_node *src, struct icc_node *dst) 1161 { 1162 struct tegra_mc *mc = icc_provider_to_tegra_mc(src->provider); 1163 const struct tegra_mc_client *client = &mc->soc->clients[src->id]; 1164 u64 peak_bandwidth = icc_units_to_bps(src->peak_bw); 1165 1166 /* 1167 * Skip pre-initialization that is done by icc_node_add(), which sets 1168 * bandwidth to maximum for all clients before drivers are loaded. 1169 * 1170 * This doesn't make sense for us because we don't have drivers for all 1171 * clients and it's okay to keep configuration left from bootloader 1172 * during boot, at least for today. 1173 */ 1174 if (src == dst) 1175 return 0; 1176 1177 /* convert bytes/sec to megabytes/sec */ 1178 do_div(peak_bandwidth, 1000000); 1179 1180 tegra30_mc_tune_client_latency(mc, client, peak_bandwidth); 1181 1182 return 0; 1183 } 1184 1185 static int tegra30_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw, 1186 u32 peak_bw, u32 *agg_avg, u32 *agg_peak) 1187 { 1188 /* 1189 * ISO clients need to reserve extra bandwidth up-front because 1190 * there could be high bandwidth pressure during initial filling 1191 * of the client's FIFO buffers. Secondly, we need to take into 1192 * account impurities of the memory subsystem. 1193 */ 1194 if (tag & TEGRA_MC_ICC_TAG_ISO) 1195 peak_bw = tegra_mc_scale_percents(peak_bw, 400); 1196 1197 *agg_avg += avg_bw; 1198 *agg_peak = max(*agg_peak, peak_bw); 1199 1200 return 0; 1201 } 1202 1203 static struct icc_node_data * 1204 tegra30_mc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data) 1205 { 1206 struct tegra_mc *mc = icc_provider_to_tegra_mc(data); 1207 const struct tegra_mc_client *client; 1208 unsigned int i, idx = spec->args[0]; 1209 struct icc_node_data *ndata; 1210 struct icc_node *node; 1211 1212 list_for_each_entry(node, &mc->provider.nodes, node_list) { 1213 if (node->id != idx) 1214 continue; 1215 1216 ndata = kzalloc(sizeof(*ndata), GFP_KERNEL); 1217 if (!ndata) 1218 return ERR_PTR(-ENOMEM); 1219 1220 client = &mc->soc->clients[idx]; 1221 ndata->node = node; 1222 1223 switch (client->swgroup) { 1224 case TEGRA_SWGROUP_DC: 1225 case TEGRA_SWGROUP_DCB: 1226 case TEGRA_SWGROUP_PTC: 1227 case TEGRA_SWGROUP_VI: 1228 /* these clients are isochronous by default */ 1229 ndata->tag = TEGRA_MC_ICC_TAG_ISO; 1230 break; 1231 1232 default: 1233 ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT; 1234 break; 1235 } 1236 1237 return ndata; 1238 } 1239 1240 for (i = 0; i < mc->soc->num_clients; i++) { 1241 if (mc->soc->clients[i].id == idx) 1242 return ERR_PTR(-EPROBE_DEFER); 1243 } 1244 1245 dev_err(mc->dev, "invalid ICC client ID %u\n", idx); 1246 1247 return ERR_PTR(-EINVAL); 1248 } 1249 1250 static const struct tegra_mc_icc_ops tegra30_mc_icc_ops = { 1251 .xlate_extended = tegra30_mc_of_icc_xlate_extended, 1252 .aggregate = tegra30_mc_icc_aggreate, 1253 .set = tegra30_mc_icc_set, 1254 }; 1255 1256 const struct tegra_mc_soc tegra30_mc_soc = { 1257 .clients = tegra30_mc_clients, 1258 .num_clients = ARRAY_SIZE(tegra30_mc_clients), 1259 .num_address_bits = 32, 1260 .atom_size = 16, 1261 .client_id_mask = 0x7f, 1262 .smmu = &tegra30_smmu_soc, 1263 .emem_regs = tegra30_mc_emem_regs, 1264 .num_emem_regs = ARRAY_SIZE(tegra30_mc_emem_regs), 1265 .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION | 1266 MC_INT_DECERR_EMEM, 1267 .reset_ops = &tegra_mc_reset_ops_common, 1268 .resets = tegra30_mc_resets, 1269 .num_resets = ARRAY_SIZE(tegra30_mc_resets), 1270 .icc_ops = &tegra30_mc_icc_ops, 1271 }; 1272