1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved. 4 */ 5 6 #include <linux/io.h> 7 #include <linux/module.h> 8 #include <linux/mod_devicetable.h> 9 #include <linux/platform_device.h> 10 11 #include <dt-bindings/memory/tegra186-mc.h> 12 13 struct tegra_mc { 14 struct device *dev; 15 void __iomem *regs; 16 }; 17 18 struct tegra_mc_client { 19 const char *name; 20 unsigned int sid; 21 struct { 22 unsigned int override; 23 unsigned int security; 24 } regs; 25 }; 26 27 static const struct tegra_mc_client tegra186_mc_clients[] = { 28 { 29 .name = "ptcr", 30 .sid = TEGRA186_SID_PASSTHROUGH, 31 .regs = { 32 .override = 0x000, 33 .security = 0x004, 34 }, 35 }, { 36 .name = "afir", 37 .sid = TEGRA186_SID_AFI, 38 .regs = { 39 .override = 0x070, 40 .security = 0x074, 41 }, 42 }, { 43 .name = "hdar", 44 .sid = TEGRA186_SID_HDA, 45 .regs = { 46 .override = 0x0a8, 47 .security = 0x0ac, 48 }, 49 }, { 50 .name = "host1xdmar", 51 .sid = TEGRA186_SID_HOST1X, 52 .regs = { 53 .override = 0x0b0, 54 .security = 0x0b4, 55 }, 56 }, { 57 .name = "nvencsrd", 58 .sid = TEGRA186_SID_NVENC, 59 .regs = { 60 .override = 0x0e0, 61 .security = 0x0e4, 62 }, 63 }, { 64 .name = "satar", 65 .sid = TEGRA186_SID_SATA, 66 .regs = { 67 .override = 0x0f8, 68 .security = 0x0fc, 69 }, 70 }, { 71 .name = "mpcorer", 72 .sid = TEGRA186_SID_PASSTHROUGH, 73 .regs = { 74 .override = 0x138, 75 .security = 0x13c, 76 }, 77 }, { 78 .name = "nvencswr", 79 .sid = TEGRA186_SID_NVENC, 80 .regs = { 81 .override = 0x158, 82 .security = 0x15c, 83 }, 84 }, { 85 .name = "afiw", 86 .sid = TEGRA186_SID_AFI, 87 .regs = { 88 .override = 0x188, 89 .security = 0x18c, 90 }, 91 }, { 92 .name = "hdaw", 93 .sid = TEGRA186_SID_HDA, 94 .regs = { 95 .override = 0x1a8, 96 .security = 0x1ac, 97 }, 98 }, { 99 .name = "mpcorew", 100 .sid = TEGRA186_SID_PASSTHROUGH, 101 .regs = { 102 .override = 0x1c8, 103 .security = 0x1cc, 104 }, 105 }, { 106 .name = "sataw", 107 .sid = TEGRA186_SID_SATA, 108 .regs = { 109 .override = 0x1e8, 110 .security = 0x1ec, 111 }, 112 }, { 113 .name = "ispra", 114 .sid = TEGRA186_SID_ISP, 115 .regs = { 116 .override = 0x220, 117 .security = 0x224, 118 }, 119 }, { 120 .name = "ispwa", 121 .sid = TEGRA186_SID_ISP, 122 .regs = { 123 .override = 0x230, 124 .security = 0x234, 125 }, 126 }, { 127 .name = "ispwb", 128 .sid = TEGRA186_SID_ISP, 129 .regs = { 130 .override = 0x238, 131 .security = 0x23c, 132 }, 133 }, { 134 .name = "xusb_hostr", 135 .sid = TEGRA186_SID_XUSB_HOST, 136 .regs = { 137 .override = 0x250, 138 .security = 0x254, 139 }, 140 }, { 141 .name = "xusb_hostw", 142 .sid = TEGRA186_SID_XUSB_HOST, 143 .regs = { 144 .override = 0x258, 145 .security = 0x25c, 146 }, 147 }, { 148 .name = "xusb_devr", 149 .sid = TEGRA186_SID_XUSB_DEV, 150 .regs = { 151 .override = 0x260, 152 .security = 0x264, 153 }, 154 }, { 155 .name = "xusb_devw", 156 .sid = TEGRA186_SID_XUSB_DEV, 157 .regs = { 158 .override = 0x268, 159 .security = 0x26c, 160 }, 161 }, { 162 .name = "tsecsrd", 163 .sid = TEGRA186_SID_TSEC, 164 .regs = { 165 .override = 0x2a0, 166 .security = 0x2a4, 167 }, 168 }, { 169 .name = "tsecswr", 170 .sid = TEGRA186_SID_TSEC, 171 .regs = { 172 .override = 0x2a8, 173 .security = 0x2ac, 174 }, 175 }, { 176 .name = "gpusrd", 177 .sid = TEGRA186_SID_GPU, 178 .regs = { 179 .override = 0x2c0, 180 .security = 0x2c4, 181 }, 182 }, { 183 .name = "gpuswr", 184 .sid = TEGRA186_SID_GPU, 185 .regs = { 186 .override = 0x2c8, 187 .security = 0x2cc, 188 }, 189 }, { 190 .name = "sdmmcra", 191 .sid = TEGRA186_SID_SDMMC1, 192 .regs = { 193 .override = 0x300, 194 .security = 0x304, 195 }, 196 }, { 197 .name = "sdmmcraa", 198 .sid = TEGRA186_SID_SDMMC2, 199 .regs = { 200 .override = 0x308, 201 .security = 0x30c, 202 }, 203 }, { 204 .name = "sdmmcr", 205 .sid = TEGRA186_SID_SDMMC3, 206 .regs = { 207 .override = 0x310, 208 .security = 0x314, 209 }, 210 }, { 211 .name = "sdmmcrab", 212 .sid = TEGRA186_SID_SDMMC4, 213 .regs = { 214 .override = 0x318, 215 .security = 0x31c, 216 }, 217 }, { 218 .name = "sdmmcwa", 219 .sid = TEGRA186_SID_SDMMC1, 220 .regs = { 221 .override = 0x320, 222 .security = 0x324, 223 }, 224 }, { 225 .name = "sdmmcwaa", 226 .sid = TEGRA186_SID_SDMMC2, 227 .regs = { 228 .override = 0x328, 229 .security = 0x32c, 230 }, 231 }, { 232 .name = "sdmmcw", 233 .sid = TEGRA186_SID_SDMMC3, 234 .regs = { 235 .override = 0x330, 236 .security = 0x334, 237 }, 238 }, { 239 .name = "sdmmcwab", 240 .sid = TEGRA186_SID_SDMMC4, 241 .regs = { 242 .override = 0x338, 243 .security = 0x33c, 244 }, 245 }, { 246 .name = "vicsrd", 247 .sid = TEGRA186_SID_VIC, 248 .regs = { 249 .override = 0x360, 250 .security = 0x364, 251 }, 252 }, { 253 .name = "vicswr", 254 .sid = TEGRA186_SID_VIC, 255 .regs = { 256 .override = 0x368, 257 .security = 0x36c, 258 }, 259 }, { 260 .name = "viw", 261 .sid = TEGRA186_SID_VI, 262 .regs = { 263 .override = 0x390, 264 .security = 0x394, 265 }, 266 }, { 267 .name = "nvdecsrd", 268 .sid = TEGRA186_SID_NVDEC, 269 .regs = { 270 .override = 0x3c0, 271 .security = 0x3c4, 272 }, 273 }, { 274 .name = "nvdecswr", 275 .sid = TEGRA186_SID_NVDEC, 276 .regs = { 277 .override = 0x3c8, 278 .security = 0x3cc, 279 }, 280 }, { 281 .name = "aper", 282 .sid = TEGRA186_SID_APE, 283 .regs = { 284 .override = 0x3d0, 285 .security = 0x3d4, 286 }, 287 }, { 288 .name = "apew", 289 .sid = TEGRA186_SID_APE, 290 .regs = { 291 .override = 0x3d8, 292 .security = 0x3dc, 293 }, 294 }, { 295 .name = "nvjpgsrd", 296 .sid = TEGRA186_SID_NVJPG, 297 .regs = { 298 .override = 0x3f0, 299 .security = 0x3f4, 300 }, 301 }, { 302 .name = "nvjpgswr", 303 .sid = TEGRA186_SID_NVJPG, 304 .regs = { 305 .override = 0x3f8, 306 .security = 0x3fc, 307 }, 308 }, { 309 .name = "sesrd", 310 .sid = TEGRA186_SID_SE, 311 .regs = { 312 .override = 0x400, 313 .security = 0x404, 314 }, 315 }, { 316 .name = "seswr", 317 .sid = TEGRA186_SID_SE, 318 .regs = { 319 .override = 0x408, 320 .security = 0x40c, 321 }, 322 }, { 323 .name = "etrr", 324 .sid = TEGRA186_SID_ETR, 325 .regs = { 326 .override = 0x420, 327 .security = 0x424, 328 }, 329 }, { 330 .name = "etrw", 331 .sid = TEGRA186_SID_ETR, 332 .regs = { 333 .override = 0x428, 334 .security = 0x42c, 335 }, 336 }, { 337 .name = "tsecsrdb", 338 .sid = TEGRA186_SID_TSECB, 339 .regs = { 340 .override = 0x430, 341 .security = 0x434, 342 }, 343 }, { 344 .name = "tsecswrb", 345 .sid = TEGRA186_SID_TSECB, 346 .regs = { 347 .override = 0x438, 348 .security = 0x43c, 349 }, 350 }, { 351 .name = "gpusrd2", 352 .sid = TEGRA186_SID_GPU, 353 .regs = { 354 .override = 0x440, 355 .security = 0x444, 356 }, 357 }, { 358 .name = "gpuswr2", 359 .sid = TEGRA186_SID_GPU, 360 .regs = { 361 .override = 0x448, 362 .security = 0x44c, 363 }, 364 }, { 365 .name = "axisr", 366 .sid = TEGRA186_SID_GPCDMA_0, 367 .regs = { 368 .override = 0x460, 369 .security = 0x464, 370 }, 371 }, { 372 .name = "axisw", 373 .sid = TEGRA186_SID_GPCDMA_0, 374 .regs = { 375 .override = 0x468, 376 .security = 0x46c, 377 }, 378 }, { 379 .name = "eqosr", 380 .sid = TEGRA186_SID_EQOS, 381 .regs = { 382 .override = 0x470, 383 .security = 0x474, 384 }, 385 }, { 386 .name = "eqosw", 387 .sid = TEGRA186_SID_EQOS, 388 .regs = { 389 .override = 0x478, 390 .security = 0x47c, 391 }, 392 }, { 393 .name = "ufshcr", 394 .sid = TEGRA186_SID_UFSHC, 395 .regs = { 396 .override = 0x480, 397 .security = 0x484, 398 }, 399 }, { 400 .name = "ufshcw", 401 .sid = TEGRA186_SID_UFSHC, 402 .regs = { 403 .override = 0x488, 404 .security = 0x48c, 405 }, 406 }, { 407 .name = "nvdisplayr", 408 .sid = TEGRA186_SID_NVDISPLAY, 409 .regs = { 410 .override = 0x490, 411 .security = 0x494, 412 }, 413 }, { 414 .name = "bpmpr", 415 .sid = TEGRA186_SID_BPMP, 416 .regs = { 417 .override = 0x498, 418 .security = 0x49c, 419 }, 420 }, { 421 .name = "bpmpw", 422 .sid = TEGRA186_SID_BPMP, 423 .regs = { 424 .override = 0x4a0, 425 .security = 0x4a4, 426 }, 427 }, { 428 .name = "bpmpdmar", 429 .sid = TEGRA186_SID_BPMP, 430 .regs = { 431 .override = 0x4a8, 432 .security = 0x4ac, 433 }, 434 }, { 435 .name = "bpmpdmaw", 436 .sid = TEGRA186_SID_BPMP, 437 .regs = { 438 .override = 0x4b0, 439 .security = 0x4b4, 440 }, 441 }, { 442 .name = "aonr", 443 .sid = TEGRA186_SID_AON, 444 .regs = { 445 .override = 0x4b8, 446 .security = 0x4bc, 447 }, 448 }, { 449 .name = "aonw", 450 .sid = TEGRA186_SID_AON, 451 .regs = { 452 .override = 0x4c0, 453 .security = 0x4c4, 454 }, 455 }, { 456 .name = "aondmar", 457 .sid = TEGRA186_SID_AON, 458 .regs = { 459 .override = 0x4c8, 460 .security = 0x4cc, 461 }, 462 }, { 463 .name = "aondmaw", 464 .sid = TEGRA186_SID_AON, 465 .regs = { 466 .override = 0x4d0, 467 .security = 0x4d4, 468 }, 469 }, { 470 .name = "scer", 471 .sid = TEGRA186_SID_SCE, 472 .regs = { 473 .override = 0x4d8, 474 .security = 0x4dc, 475 }, 476 }, { 477 .name = "scew", 478 .sid = TEGRA186_SID_SCE, 479 .regs = { 480 .override = 0x4e0, 481 .security = 0x4e4, 482 }, 483 }, { 484 .name = "scedmar", 485 .sid = TEGRA186_SID_SCE, 486 .regs = { 487 .override = 0x4e8, 488 .security = 0x4ec, 489 }, 490 }, { 491 .name = "scedmaw", 492 .sid = TEGRA186_SID_SCE, 493 .regs = { 494 .override = 0x4f0, 495 .security = 0x4f4, 496 }, 497 }, { 498 .name = "apedmar", 499 .sid = TEGRA186_SID_APE, 500 .regs = { 501 .override = 0x4f8, 502 .security = 0x4fc, 503 }, 504 }, { 505 .name = "apedmaw", 506 .sid = TEGRA186_SID_APE, 507 .regs = { 508 .override = 0x500, 509 .security = 0x504, 510 }, 511 }, { 512 .name = "nvdisplayr1", 513 .sid = TEGRA186_SID_NVDISPLAY, 514 .regs = { 515 .override = 0x508, 516 .security = 0x50c, 517 }, 518 }, { 519 .name = "vicsrd1", 520 .sid = TEGRA186_SID_VIC, 521 .regs = { 522 .override = 0x510, 523 .security = 0x514, 524 }, 525 }, { 526 .name = "nvdecsrd1", 527 .sid = TEGRA186_SID_NVDEC, 528 .regs = { 529 .override = 0x518, 530 .security = 0x51c, 531 }, 532 }, 533 }; 534 535 static int tegra186_mc_probe(struct platform_device *pdev) 536 { 537 struct resource *res; 538 struct tegra_mc *mc; 539 unsigned int i; 540 int err = 0; 541 542 mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); 543 if (!mc) 544 return -ENOMEM; 545 546 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 547 mc->regs = devm_ioremap_resource(&pdev->dev, res); 548 if (IS_ERR(mc->regs)) 549 return PTR_ERR(mc->regs); 550 551 mc->dev = &pdev->dev; 552 553 for (i = 0; i < ARRAY_SIZE(tegra186_mc_clients); i++) { 554 const struct tegra_mc_client *client = &tegra186_mc_clients[i]; 555 u32 override, security; 556 557 override = readl(mc->regs + client->regs.override); 558 security = readl(mc->regs + client->regs.security); 559 560 dev_dbg(&pdev->dev, "client %s: override: %x security: %x\n", 561 client->name, override, security); 562 563 dev_dbg(&pdev->dev, "setting SID %u for %s\n", client->sid, 564 client->name); 565 writel(client->sid, mc->regs + client->regs.override); 566 567 override = readl(mc->regs + client->regs.override); 568 security = readl(mc->regs + client->regs.security); 569 570 dev_dbg(&pdev->dev, "client %s: override: %x security: %x\n", 571 client->name, override, security); 572 } 573 574 platform_set_drvdata(pdev, mc); 575 576 return err; 577 } 578 579 static const struct of_device_id tegra186_mc_of_match[] = { 580 { .compatible = "nvidia,tegra186-mc", }, 581 { /* sentinel */ } 582 }; 583 MODULE_DEVICE_TABLE(of, tegra186_mc_of_match); 584 585 static struct platform_driver tegra186_mc_driver = { 586 .driver = { 587 .name = "tegra186-mc", 588 .of_match_table = tegra186_mc_of_match, 589 .suppress_bind_attrs = true, 590 }, 591 .prevent_deferred_probe = true, 592 .probe = tegra186_mc_probe, 593 }; 594 module_platform_driver(tegra186_mc_driver); 595 596 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); 597 MODULE_DESCRIPTION("NVIDIA Tegra186 Memory Controller driver"); 598 MODULE_LICENSE("GPL v2"); 599