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