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