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