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