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
tegra186_mc_probe(struct platform_device * pdev)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