xref: /linux/drivers/memory/tegra/tegra114.c (revision 6505114e82e7541414b176b5da4a3c015a1214ea)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2014-2026 NVIDIA CORPORATION.  All rights reserved.
4  */
5 
6 #include <linux/device.h>
7 #include <linux/of.h>
8 #include <linux/mm.h>
9 
10 #include <dt-bindings/memory/tegra114-mc.h>
11 
12 #include "mc.h"
13 
14 static const struct tegra_mc_client tegra114_mc_clients[] = {
15 	{
16 		.id = 0x00,
17 		.name = "ptcr",
18 		.swgroup = TEGRA_SWGROUP_PTC,
19 		.regs = {
20 			.la = {
21 				.reg = 0x34c,
22 				.shift = 0,
23 				.mask = 0xff,
24 				.def = 0x0,
25 			},
26 		},
27 	}, {
28 		.id = 0x01,
29 		.name = "display0a",
30 		.swgroup = TEGRA_SWGROUP_DC,
31 		.regs = {
32 			.smmu = {
33 				.reg = 0x228,
34 				.bit = 1,
35 			},
36 			.la = {
37 				.reg = 0x2e8,
38 				.shift = 0,
39 				.mask = 0xff,
40 				.def = 0x4e,
41 			},
42 		},
43 	}, {
44 		.id = 0x02,
45 		.name = "display0ab",
46 		.swgroup = TEGRA_SWGROUP_DCB,
47 		.regs = {
48 			.smmu = {
49 				.reg = 0x228,
50 				.bit = 2,
51 			},
52 			.la = {
53 				.reg = 0x2f4,
54 				.shift = 0,
55 				.mask = 0xff,
56 				.def = 0x4e,
57 			},
58 		},
59 	}, {
60 		.id = 0x03,
61 		.name = "display0b",
62 		.swgroup = TEGRA_SWGROUP_DC,
63 		.regs = {
64 			.smmu = {
65 				.reg = 0x228,
66 				.bit = 3,
67 			},
68 			.la = {
69 				.reg = 0x2e8,
70 				.shift = 16,
71 				.mask = 0xff,
72 				.def = 0x4e,
73 			},
74 		},
75 	}, {
76 		.id = 0x04,
77 		.name = "display0bb",
78 		.swgroup = TEGRA_SWGROUP_DCB,
79 		.regs = {
80 			.smmu = {
81 				.reg = 0x228,
82 				.bit = 4,
83 			},
84 			.la = {
85 				.reg = 0x2f4,
86 				.shift = 16,
87 				.mask = 0xff,
88 				.def = 0x4e,
89 			},
90 		},
91 	}, {
92 		.id = 0x05,
93 		.name = "display0c",
94 		.swgroup = TEGRA_SWGROUP_DC,
95 		.regs = {
96 			.smmu = {
97 				.reg = 0x228,
98 				.bit = 5,
99 			},
100 			.la = {
101 				.reg = 0x2ec,
102 				.shift = 0,
103 				.mask = 0xff,
104 				.def = 0x4e,
105 			},
106 		},
107 	}, {
108 		.id = 0x06,
109 		.name = "display0cb",
110 		.swgroup = TEGRA_SWGROUP_DCB,
111 		.regs = {
112 			.smmu = {
113 				.reg = 0x228,
114 				.bit = 6,
115 			},
116 			.la = {
117 				.reg = 0x2f8,
118 				.shift = 0,
119 				.mask = 0xff,
120 				.def = 0x4e,
121 			},
122 		},
123 	}, {
124 		.id = 0x09,
125 		.name = "eppup",
126 		.swgroup = TEGRA_SWGROUP_EPP,
127 		.regs = {
128 			.smmu = {
129 				.reg = 0x228,
130 				.bit = 9,
131 			},
132 			.la = {
133 				.reg = 0x300,
134 				.shift = 0,
135 				.mask = 0xff,
136 				.def = 0x33,
137 			},
138 		},
139 	}, {
140 		.id = 0x0a,
141 		.name = "g2pr",
142 		.swgroup = TEGRA_SWGROUP_G2,
143 		.regs = {
144 			.smmu = {
145 				.reg = 0x228,
146 				.bit = 10,
147 			},
148 			.la = {
149 				.reg = 0x308,
150 				.shift = 0,
151 				.mask = 0xff,
152 				.def = 0x09,
153 			},
154 		},
155 	}, {
156 		.id = 0x0b,
157 		.name = "g2sr",
158 		.swgroup = TEGRA_SWGROUP_G2,
159 		.regs = {
160 			.smmu = {
161 				.reg = 0x228,
162 				.bit = 11,
163 			},
164 			.la = {
165 				.reg = 0x308,
166 				.shift = 16,
167 				.mask = 0xff,
168 				.def = 0x09,
169 			},
170 		},
171 	}, {
172 		.id = 0x0f,
173 		.name = "avpcarm7r",
174 		.swgroup = TEGRA_SWGROUP_AVPC,
175 		.regs = {
176 			.smmu = {
177 				.reg = 0x228,
178 				.bit = 15,
179 			},
180 			.la = {
181 				.reg = 0x2e4,
182 				.shift = 0,
183 				.mask = 0xff,
184 				.def = 0x04,
185 			},
186 		},
187 	}, {
188 		.id = 0x10,
189 		.name = "displayhc",
190 		.swgroup = TEGRA_SWGROUP_DC,
191 		.regs = {
192 			.smmu = {
193 				.reg = 0x228,
194 				.bit = 16,
195 			},
196 			.la = {
197 				.reg = 0x2f0,
198 				.shift = 0,
199 				.mask = 0xff,
200 				.def = 0x68,
201 			},
202 		},
203 	}, {
204 		.id = 0x11,
205 		.name = "displayhcb",
206 		.swgroup = TEGRA_SWGROUP_DCB,
207 		.regs = {
208 			.smmu = {
209 				.reg = 0x228,
210 				.bit = 17,
211 			},
212 			.la = {
213 				.reg = 0x2fc,
214 				.shift = 0,
215 				.mask = 0xff,
216 				.def = 0x68,
217 			},
218 		},
219 	}, {
220 		.id = 0x12,
221 		.name = "fdcdrd",
222 		.swgroup = TEGRA_SWGROUP_NV,
223 		.regs = {
224 			.smmu = {
225 				.reg = 0x228,
226 				.bit = 18,
227 			},
228 			.la = {
229 				.reg = 0x334,
230 				.shift = 0,
231 				.mask = 0xff,
232 				.def = 0x0c,
233 			},
234 		},
235 	}, {
236 		.id = 0x13,
237 		.name = "fdcdrd2",
238 		.swgroup = TEGRA_SWGROUP_NV,
239 		.regs = {
240 			.smmu = {
241 				.reg = 0x228,
242 				.bit = 19,
243 			},
244 			.la = {
245 				.reg = 0x33c,
246 				.shift = 0,
247 				.mask = 0xff,
248 				.def = 0x0c,
249 			},
250 		},
251 	}, {
252 		.id = 0x14,
253 		.name = "g2dr",
254 		.swgroup = TEGRA_SWGROUP_G2,
255 		.regs = {
256 			.smmu = {
257 				.reg = 0x228,
258 				.bit = 20,
259 			},
260 			.la = {
261 				.reg = 0x30c,
262 				.shift = 0,
263 				.mask = 0xff,
264 				.def = 0x0a,
265 			},
266 		},
267 	}, {
268 		.id = 0x15,
269 		.name = "hdar",
270 		.swgroup = TEGRA_SWGROUP_HDA,
271 		.regs = {
272 			.smmu = {
273 				.reg = 0x228,
274 				.bit = 21,
275 			},
276 			.la = {
277 				.reg = 0x318,
278 				.shift = 0,
279 				.mask = 0xff,
280 				.def = 0xff,
281 			},
282 		},
283 	}, {
284 		.id = 0x16,
285 		.name = "host1xdmar",
286 		.swgroup = TEGRA_SWGROUP_HC,
287 		.regs = {
288 			.smmu = {
289 				.reg = 0x228,
290 				.bit = 22,
291 			},
292 			.la = {
293 				.reg = 0x310,
294 				.shift = 0,
295 				.mask = 0xff,
296 				.def = 0x10,
297 			},
298 		},
299 	}, {
300 		.id = 0x17,
301 		.name = "host1xr",
302 		.swgroup = TEGRA_SWGROUP_HC,
303 		.regs = {
304 			.smmu = {
305 				.reg = 0x228,
306 				.bit = 23,
307 			},
308 			.la = {
309 				.reg = 0x310,
310 				.shift = 16,
311 				.mask = 0xff,
312 				.def = 0xa5,
313 			},
314 		},
315 	}, {
316 		.id = 0x18,
317 		.name = "idxsrd",
318 		.swgroup = TEGRA_SWGROUP_NV,
319 		.regs = {
320 			.smmu = {
321 				.reg = 0x228,
322 				.bit = 24,
323 			},
324 			.la = {
325 				.reg = 0x334,
326 				.shift = 16,
327 				.mask = 0xff,
328 				.def = 0x0b,
329 			},
330 		},
331 	}, {
332 		.id = 0x1c,
333 		.name = "msencsrd",
334 		.swgroup = TEGRA_SWGROUP_MSENC,
335 		.regs = {
336 			.smmu = {
337 				.reg = 0x228,
338 				.bit = 28,
339 			},
340 			.la = {
341 				.reg = 0x328,
342 				.shift = 0,
343 				.mask = 0xff,
344 				.def = 0x80,
345 			},
346 		},
347 	}, {
348 		.id = 0x1d,
349 		.name = "ppcsahbdmar",
350 		.swgroup = TEGRA_SWGROUP_PPCS,
351 		.regs = {
352 			.smmu = {
353 				.reg = 0x228,
354 				.bit = 29,
355 			},
356 			.la = {
357 				.reg = 0x344,
358 				.shift = 0,
359 				.mask = 0xff,
360 				.def = 0x50,
361 			},
362 		},
363 	}, {
364 		.id = 0x1e,
365 		.name = "ppcsahbslvr",
366 		.swgroup = TEGRA_SWGROUP_PPCS,
367 		.regs = {
368 			.smmu = {
369 				.reg = 0x228,
370 				.bit = 30,
371 			},
372 			.la = {
373 				.reg = 0x344,
374 				.shift = 16,
375 				.mask = 0xff,
376 				.def = 0xe8,
377 			},
378 		},
379 	}, {
380 		.id = 0x20,
381 		.name = "texl2srd",
382 		.swgroup = TEGRA_SWGROUP_NV,
383 		.regs = {
384 			.smmu = {
385 				.reg = 0x22c,
386 				.bit = 0,
387 			},
388 			.la = {
389 				.reg = 0x338,
390 				.shift = 0,
391 				.mask = 0xff,
392 				.def = 0x0c,
393 			},
394 		},
395 	}, {
396 		.id = 0x22,
397 		.name = "vdebsevr",
398 		.swgroup = TEGRA_SWGROUP_VDE,
399 		.regs = {
400 			.smmu = {
401 				.reg = 0x22c,
402 				.bit = 2,
403 			},
404 			.la = {
405 				.reg = 0x354,
406 				.shift = 0,
407 				.mask = 0xff,
408 				.def = 0xff,
409 			},
410 		},
411 	}, {
412 		.id = 0x23,
413 		.name = "vdember",
414 		.swgroup = TEGRA_SWGROUP_VDE,
415 		.regs = {
416 			.smmu = {
417 				.reg = 0x22c,
418 				.bit = 3,
419 			},
420 			.la = {
421 				.reg = 0x354,
422 				.shift = 16,
423 				.mask = 0xff,
424 				.def = 0xff,
425 			},
426 		},
427 	}, {
428 		.id = 0x24,
429 		.name = "vdemcer",
430 		.swgroup = TEGRA_SWGROUP_VDE,
431 		.regs = {
432 			.smmu = {
433 				.reg = 0x22c,
434 				.bit = 4,
435 			},
436 			.la = {
437 				.reg = 0x358,
438 				.shift = 0,
439 				.mask = 0xff,
440 				.def = 0xb8,
441 			},
442 		},
443 	}, {
444 		.id = 0x25,
445 		.name = "vdetper",
446 		.swgroup = TEGRA_SWGROUP_VDE,
447 		.regs = {
448 			.smmu = {
449 				.reg = 0x22c,
450 				.bit = 5,
451 			},
452 			.la = {
453 				.reg = 0x358,
454 				.shift = 16,
455 				.mask = 0xff,
456 				.def = 0xee,
457 			},
458 		},
459 	}, {
460 		.id = 0x26,
461 		.name = "mpcorelpr",
462 		.swgroup = TEGRA_SWGROUP_MPCORELP,
463 		.regs = {
464 			.la = {
465 				.reg = 0x324,
466 				.shift = 0,
467 				.mask = 0xff,
468 				.def = 0x04,
469 			},
470 		},
471 	}, {
472 		.id = 0x27,
473 		.name = "mpcorer",
474 		.swgroup = TEGRA_SWGROUP_MPCORE,
475 		.regs = {
476 			.la = {
477 				.reg = 0x320,
478 				.shift = 0,
479 				.mask = 0xff,
480 				.def = 0x04,
481 			},
482 		},
483 	}, {
484 		.id = 0x28,
485 		.name = "eppu",
486 		.swgroup = TEGRA_SWGROUP_EPP,
487 		.regs = {
488 			.smmu = {
489 				.reg = 0x22c,
490 				.bit = 8,
491 			},
492 			.la = {
493 				.reg = 0x300,
494 				.shift = 16,
495 				.mask = 0xff,
496 				.def = 0x33,
497 			},
498 		},
499 	}, {
500 		.id = 0x29,
501 		.name = "eppv",
502 		.swgroup = TEGRA_SWGROUP_EPP,
503 		.regs = {
504 			.smmu = {
505 				.reg = 0x22c,
506 				.bit = 9,
507 			},
508 			.la = {
509 				.reg = 0x304,
510 				.shift = 0,
511 				.mask = 0xff,
512 				.def = 0x6c,
513 			},
514 		},
515 	}, {
516 		.id = 0x2a,
517 		.name = "eppy",
518 		.swgroup = TEGRA_SWGROUP_EPP,
519 		.regs = {
520 			.smmu = {
521 				.reg = 0x22c,
522 				.bit = 10,
523 			},
524 			.la = {
525 				.reg = 0x304,
526 				.shift = 16,
527 				.mask = 0xff,
528 				.def = 0x6c,
529 			},
530 		},
531 	}, {
532 		.id = 0x2b,
533 		.name = "msencswr",
534 		.swgroup = TEGRA_SWGROUP_MSENC,
535 		.regs = {
536 			.smmu = {
537 				.reg = 0x22c,
538 				.bit = 11,
539 			},
540 			.la = {
541 				.reg = 0x328,
542 				.shift = 16,
543 				.mask = 0xff,
544 				.def = 0x80,
545 			},
546 		},
547 	}, {
548 		.id = 0x2c,
549 		.name = "viwsb",
550 		.swgroup = TEGRA_SWGROUP_VI,
551 		.regs = {
552 			.smmu = {
553 				.reg = 0x22c,
554 				.bit = 12,
555 			},
556 			.la = {
557 				.reg = 0x364,
558 				.shift = 0,
559 				.mask = 0xff,
560 				.def = 0x47,
561 			},
562 		},
563 	}, {
564 		.id = 0x2d,
565 		.name = "viwu",
566 		.swgroup = TEGRA_SWGROUP_VI,
567 		.regs = {
568 			.smmu = {
569 				.reg = 0x22c,
570 				.bit = 13,
571 			},
572 			.la = {
573 				.reg = 0x368,
574 				.shift = 0,
575 				.mask = 0xff,
576 				.def = 0xff,
577 			},
578 		},
579 	}, {
580 		.id = 0x2e,
581 		.name = "viwv",
582 		.swgroup = TEGRA_SWGROUP_VI,
583 		.regs = {
584 			.smmu = {
585 				.reg = 0x22c,
586 				.bit = 14,
587 			},
588 			.la = {
589 				.reg = 0x368,
590 				.shift = 16,
591 				.mask = 0xff,
592 				.def = 0xff,
593 			},
594 		},
595 	}, {
596 		.id = 0x2f,
597 		.name = "viwy",
598 		.swgroup = TEGRA_SWGROUP_VI,
599 		.regs = {
600 			.smmu = {
601 				.reg = 0x22c,
602 				.bit = 15,
603 			},
604 			.la = {
605 				.reg = 0x36c,
606 				.shift = 0,
607 				.mask = 0xff,
608 				.def = 0x47,
609 			},
610 		},
611 	}, {
612 		.id = 0x30,
613 		.name = "g2dw",
614 		.swgroup = TEGRA_SWGROUP_G2,
615 		.regs = {
616 			.smmu = {
617 				.reg = 0x22c,
618 				.bit = 16,
619 			},
620 			.la = {
621 				.reg = 0x30c,
622 				.shift = 16,
623 				.mask = 0xff,
624 				.def = 0x9,
625 			},
626 		},
627 	}, {
628 		.id = 0x32,
629 		.name = "avpcarm7w",
630 		.swgroup = TEGRA_SWGROUP_AVPC,
631 		.regs = {
632 			.smmu = {
633 				.reg = 0x22c,
634 				.bit = 18,
635 			},
636 			.la = {
637 				.reg = 0x2e4,
638 				.shift = 16,
639 				.mask = 0xff,
640 				.def = 0x0e,
641 			},
642 		},
643 	}, {
644 		.id = 0x33,
645 		.name = "fdcdwr",
646 		.swgroup = TEGRA_SWGROUP_NV,
647 		.regs = {
648 			.smmu = {
649 				.reg = 0x22c,
650 				.bit = 19,
651 			},
652 			.la = {
653 				.reg = 0x338,
654 				.shift = 16,
655 				.mask = 0xff,
656 				.def = 0x10,
657 			},
658 		},
659 	}, {
660 		.id = 0x34,
661 		.name = "fdcdwr2",
662 		.swgroup = TEGRA_SWGROUP_NV,
663 		.regs = {
664 			.smmu = {
665 				.reg = 0x22c,
666 				.bit = 20,
667 			},
668 			.la = {
669 				.reg = 0x340,
670 				.shift = 0,
671 				.mask = 0xff,
672 				.def = 0x10,
673 			},
674 		},
675 	}, {
676 		.id = 0x35,
677 		.name = "hdaw",
678 		.swgroup = TEGRA_SWGROUP_HDA,
679 		.regs = {
680 			.smmu = {
681 				.reg = 0x22c,
682 				.bit = 21,
683 			},
684 			.la = {
685 				.reg = 0x318,
686 				.shift = 16,
687 				.mask = 0xff,
688 				.def = 0xff,
689 			},
690 		},
691 	}, {
692 		.id = 0x36,
693 		.name = "host1xw",
694 		.swgroup = TEGRA_SWGROUP_HC,
695 		.regs = {
696 			.smmu = {
697 				.reg = 0x22c,
698 				.bit = 22,
699 			},
700 			.la = {
701 				.reg = 0x314,
702 				.shift = 0,
703 				.mask = 0xff,
704 				.def = 0x25,
705 			},
706 		},
707 	}, {
708 		.id = 0x37,
709 		.name = "ispw",
710 		.swgroup = TEGRA_SWGROUP_ISP,
711 		.regs = {
712 			.smmu = {
713 				.reg = 0x22c,
714 				.bit = 23,
715 			},
716 			.la = {
717 				.reg = 0x31c,
718 				.shift = 0,
719 				.mask = 0xff,
720 				.def = 0xff,
721 			},
722 		},
723 	}, {
724 		.id = 0x38,
725 		.name = "mpcorelpw",
726 		.swgroup = TEGRA_SWGROUP_MPCORELP,
727 		.regs = {
728 			.la = {
729 				.reg = 0x324,
730 				.shift = 16,
731 				.mask = 0xff,
732 				.def = 0x80,
733 			},
734 		},
735 	}, {
736 		.id = 0x39,
737 		.name = "mpcorew",
738 		.swgroup = TEGRA_SWGROUP_MPCORE,
739 		.regs = {
740 			.la = {
741 				.reg = 0x320,
742 				.shift = 16,
743 				.mask = 0xff,
744 				.def = 0x0e,
745 			},
746 		},
747 	}, {
748 		.id = 0x3b,
749 		.name = "ppcsahbdmaw",
750 		.swgroup = TEGRA_SWGROUP_PPCS,
751 		.regs = {
752 			.smmu = {
753 				.reg = 0x22c,
754 				.bit = 27,
755 			},
756 			.la = {
757 				.reg = 0x348,
758 				.shift = 0,
759 				.mask = 0xff,
760 				.def = 0xa5,
761 			},
762 		},
763 	}, {
764 		.id = 0x3c,
765 		.name = "ppcsahbslvw",
766 		.swgroup = TEGRA_SWGROUP_PPCS,
767 		.regs = {
768 			.smmu = {
769 				.reg = 0x22c,
770 				.bit = 28,
771 			},
772 			.la = {
773 				.reg = 0x348,
774 				.shift = 16,
775 				.mask = 0xff,
776 				.def = 0xe8,
777 			},
778 		},
779 	}, {
780 		.id = 0x3e,
781 		.name = "vdebsevw",
782 		.swgroup = TEGRA_SWGROUP_VDE,
783 		.regs = {
784 			.smmu = {
785 				.reg = 0x22c,
786 				.bit = 30,
787 			},
788 			.la = {
789 				.reg = 0x35c,
790 				.shift = 0,
791 				.mask = 0xff,
792 				.def = 0xff,
793 			},
794 		},
795 	}, {
796 		.id = 0x3f,
797 		.name = "vdedbgw",
798 		.swgroup = TEGRA_SWGROUP_VDE,
799 		.regs = {
800 			.smmu = {
801 				.reg = 0x22c,
802 				.bit = 31,
803 			},
804 			.la = {
805 				.reg = 0x35c,
806 				.shift = 16,
807 				.mask = 0xff,
808 				.def = 0xff,
809 			},
810 		},
811 	}, {
812 		.id = 0x40,
813 		.name = "vdembew",
814 		.swgroup = TEGRA_SWGROUP_VDE,
815 		.regs = {
816 			.smmu = {
817 				.reg = 0x230,
818 				.bit = 0,
819 			},
820 			.la = {
821 				.reg = 0x360,
822 				.shift = 0,
823 				.mask = 0xff,
824 				.def = 0x89,
825 			},
826 		},
827 	}, {
828 		.id = 0x41,
829 		.name = "vdetpmw",
830 		.swgroup = TEGRA_SWGROUP_VDE,
831 		.regs = {
832 			.smmu = {
833 				.reg = 0x230,
834 				.bit = 1,
835 			},
836 			.la = {
837 				.reg = 0x360,
838 				.shift = 16,
839 				.mask = 0xff,
840 				.def = 0x59,
841 			},
842 		},
843 	}, {
844 		.id = 0x4a,
845 		.name = "xusb_hostr",
846 		.swgroup = TEGRA_SWGROUP_XUSB_HOST,
847 		.regs = {
848 			.smmu = {
849 				.reg = 0x230,
850 				.bit = 10,
851 			},
852 			.la = {
853 				.reg = 0x37c,
854 				.shift = 0,
855 				.mask = 0xff,
856 				.def = 0xa5,
857 			},
858 		},
859 	}, {
860 		.id = 0x4b,
861 		.name = "xusb_hostw",
862 		.swgroup = TEGRA_SWGROUP_XUSB_HOST,
863 		.regs = {
864 			.smmu = {
865 				.reg = 0x230,
866 				.bit = 11,
867 			},
868 			.la = {
869 				.reg = 0x37c,
870 				.shift = 16,
871 				.mask = 0xff,
872 				.def = 0xa5,
873 			},
874 		},
875 	}, {
876 		.id = 0x4c,
877 		.name = "xusb_devr",
878 		.swgroup = TEGRA_SWGROUP_XUSB_DEV,
879 		.regs = {
880 			.smmu = {
881 				.reg = 0x230,
882 				.bit = 12,
883 			},
884 			.la = {
885 				.reg = 0x380,
886 				.shift = 0,
887 				.mask = 0xff,
888 				.def = 0xa5,
889 			},
890 		},
891 	}, {
892 		.id = 0x4d,
893 		.name = "xusb_devw",
894 		.swgroup = TEGRA_SWGROUP_XUSB_DEV,
895 		.regs = {
896 			.smmu = {
897 				.reg = 0x230,
898 				.bit = 13,
899 			},
900 			.la = {
901 				.reg = 0x380,
902 				.shift = 16,
903 				.mask = 0xff,
904 				.def = 0xa5,
905 			},
906 		},
907 	}, {
908 		.id = 0x4e,
909 		.name = "fdcdwr3",
910 		.swgroup = TEGRA_SWGROUP_NV,
911 		.regs = {
912 			.smmu = {
913 				.reg = 0x230,
914 				.bit = 14,
915 			},
916 			.la = {
917 				.reg = 0x388,
918 				.shift = 0,
919 				.mask = 0xff,
920 				.def = 0x10,
921 			},
922 		},
923 	}, {
924 		.id = 0x4f,
925 		.name = "fdcdrd3",
926 		.swgroup = TEGRA_SWGROUP_NV,
927 		.regs = {
928 			.smmu = {
929 				.reg = 0x230,
930 				.bit = 15,
931 			},
932 			.la = {
933 				.reg = 0x384,
934 				.shift = 0,
935 				.mask = 0xff,
936 				.def = 0x0c,
937 			},
938 		},
939 	}, {
940 		.id = 0x50,
941 		.name = "fdcwr4",
942 		.swgroup = TEGRA_SWGROUP_NV,
943 		.regs = {
944 			.smmu = {
945 				.reg = 0x230,
946 				.bit = 16,
947 			},
948 			.la = {
949 				.reg = 0x388,
950 				.shift = 16,
951 				.mask = 0xff,
952 				.def = 0x10,
953 			},
954 		},
955 	}, {
956 		.id = 0x51,
957 		.name = "fdcrd4",
958 		.swgroup = TEGRA_SWGROUP_NV,
959 		.regs = {
960 			.smmu = {
961 				.reg = 0x230,
962 				.bit = 17,
963 			},
964 			.la = {
965 				.reg = 0x384,
966 				.shift = 16,
967 				.mask = 0xff,
968 				.def = 0x0c,
969 			},
970 		},
971 	}, {
972 		.id = 0x52,
973 		.name = "emucifr",
974 		.swgroup = TEGRA_SWGROUP_EMUCIF,
975 		.regs = {
976 			.la = {
977 				.reg = 0x38c,
978 				.shift = 0,
979 				.mask = 0xff,
980 				.def = 0x04,
981 			},
982 		},
983 	}, {
984 		.id = 0x53,
985 		.name = "emucifw",
986 		.swgroup = TEGRA_SWGROUP_EMUCIF,
987 		.regs = {
988 			.la = {
989 				.reg = 0x38c,
990 				.shift = 16,
991 				.mask = 0xff,
992 				.def = 0x0e,
993 			},
994 		},
995 	}, {
996 		.id = 0x54,
997 		.name = "tsecsrd",
998 		.swgroup = TEGRA_SWGROUP_TSEC,
999 		.regs = {
1000 			.smmu = {
1001 				.reg = 0x230,
1002 				.bit = 20,
1003 			},
1004 			.la = {
1005 				.reg = 0x390,
1006 				.shift = 0,
1007 				.mask = 0xff,
1008 				.def = 0x50,
1009 			},
1010 		},
1011 	}, {
1012 		.id = 0x55,
1013 		.name = "tsecswr",
1014 		.swgroup = TEGRA_SWGROUP_TSEC,
1015 		.regs = {
1016 			.smmu = {
1017 				.reg = 0x230,
1018 				.bit = 21,
1019 			},
1020 			.la = {
1021 				.reg = 0x390,
1022 				.shift = 16,
1023 				.mask = 0xff,
1024 				.def = 0x50,
1025 			},
1026 		},
1027 	},
1028 };
1029 
1030 static const struct tegra_smmu_swgroup tegra114_swgroups[] = {
1031 	{ .name = "dc",        .swgroup = TEGRA_SWGROUP_DC,        .reg = 0x240 },
1032 	{ .name = "dcb",       .swgroup = TEGRA_SWGROUP_DCB,       .reg = 0x244 },
1033 	{ .name = "epp",       .swgroup = TEGRA_SWGROUP_EPP,       .reg = 0x248 },
1034 	{ .name = "g2",        .swgroup = TEGRA_SWGROUP_G2,        .reg = 0x24c },
1035 	{ .name = "avpc",      .swgroup = TEGRA_SWGROUP_AVPC,      .reg = 0x23c },
1036 	{ .name = "nv",        .swgroup = TEGRA_SWGROUP_NV,        .reg = 0x268 },
1037 	{ .name = "hda",       .swgroup = TEGRA_SWGROUP_HDA,       .reg = 0x254 },
1038 	{ .name = "hc",        .swgroup = TEGRA_SWGROUP_HC,        .reg = 0x250 },
1039 	{ .name = "msenc",     .swgroup = TEGRA_SWGROUP_MSENC,     .reg = 0x264 },
1040 	{ .name = "ppcs",      .swgroup = TEGRA_SWGROUP_PPCS,      .reg = 0x270 },
1041 	{ .name = "vde",       .swgroup = TEGRA_SWGROUP_VDE,       .reg = 0x27c },
1042 	{ .name = "vi",        .swgroup = TEGRA_SWGROUP_VI,        .reg = 0x280 },
1043 	{ .name = "isp",       .swgroup = TEGRA_SWGROUP_ISP,       .reg = 0x258 },
1044 	{ .name = "xusb_host", .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 },
1045 	{ .name = "xusb_dev",  .swgroup = TEGRA_SWGROUP_XUSB_DEV,  .reg = 0x28c },
1046 	{ .name = "tsec",      .swgroup = TEGRA_SWGROUP_TSEC,      .reg = 0x294 },
1047 };
1048 
1049 static const unsigned int tegra114_group_drm[] = {
1050 	TEGRA_SWGROUP_DC,
1051 	TEGRA_SWGROUP_DCB,
1052 	TEGRA_SWGROUP_G2,
1053 	TEGRA_SWGROUP_NV,
1054 };
1055 
1056 static const struct tegra_smmu_group_soc tegra114_groups[] = {
1057 	{
1058 		.name = "drm",
1059 		.swgroups = tegra114_group_drm,
1060 		.num_swgroups = ARRAY_SIZE(tegra114_group_drm),
1061 	},
1062 };
1063 
1064 static const struct tegra_smmu_soc tegra114_smmu_soc = {
1065 	.clients = tegra114_mc_clients,
1066 	.num_clients = ARRAY_SIZE(tegra114_mc_clients),
1067 	.swgroups = tegra114_swgroups,
1068 	.num_swgroups = ARRAY_SIZE(tegra114_swgroups),
1069 	.groups = tegra114_groups,
1070 	.num_groups = ARRAY_SIZE(tegra114_groups),
1071 	.supports_round_robin_arbitration = false,
1072 	.supports_request_limit = false,
1073 	.num_tlb_lines = 32,
1074 	.num_asids = 4,
1075 };
1076 
1077 #define TEGRA114_MC_RESET(_name, _control, _status, _bit)	\
1078 	{							\
1079 		.name = #_name,					\
1080 		.id = TEGRA114_MC_RESET_##_name,		\
1081 		.control = _control,				\
1082 		.status = _status,				\
1083 		.bit = _bit,					\
1084 	}
1085 
1086 static const struct tegra_mc_reset tegra114_mc_resets[] = {
1087 	TEGRA114_MC_RESET(AVPC,     0x200, 0x204,  1),
1088 	TEGRA114_MC_RESET(DC,       0x200, 0x204,  2),
1089 	TEGRA114_MC_RESET(DCB,      0x200, 0x204,  3),
1090 	TEGRA114_MC_RESET(EPP,      0x200, 0x204,  4),
1091 	TEGRA114_MC_RESET(2D,       0x200, 0x204,  5),
1092 	TEGRA114_MC_RESET(HC,       0x200, 0x204,  6),
1093 	TEGRA114_MC_RESET(HDA,      0x200, 0x204,  7),
1094 	TEGRA114_MC_RESET(ISP,      0x200, 0x204,  8),
1095 	TEGRA114_MC_RESET(MPCORE,   0x200, 0x204,  9),
1096 	TEGRA114_MC_RESET(MPCORELP, 0x200, 0x204, 10),
1097 	TEGRA114_MC_RESET(MPE,      0x200, 0x204, 11),
1098 	TEGRA114_MC_RESET(3D,       0x200, 0x204, 12),
1099 	TEGRA114_MC_RESET(3D2,      0x200, 0x204, 13),
1100 	TEGRA114_MC_RESET(PPCS,     0x200, 0x204, 14),
1101 	TEGRA114_MC_RESET(VDE,      0x200, 0x204, 16),
1102 	TEGRA114_MC_RESET(VI,       0x200, 0x204, 17),
1103 };
1104 
1105 static void tegra114_mc_tune_client_latency(struct tegra_mc *mc,
1106 					    const struct tegra_mc_client *client,
1107 					    unsigned int bandwidth_mbytes_sec)
1108 {
1109 	u32 arb_tolerance_compensation_nsec, arb_tolerance_compensation_div;
1110 	unsigned int fifo_size = client->fifo_size;
1111 	u32 arb_nsec, la_ticks, value;
1112 
1113 	/* see 20.3.1.1 Client Configuration in Tegra4 TRM v01p */
1114 	if (bandwidth_mbytes_sec)
1115 		arb_nsec = fifo_size * NSEC_PER_USEC / bandwidth_mbytes_sec;
1116 	else
1117 		arb_nsec = U32_MAX;
1118 
1119 	/*
1120 	 * Latency allowness should be set with consideration for the module's
1121 	 * latency tolerance and internal buffering capabilities.
1122 	 *
1123 	 * Display memory clients use isochronous transfers and have very low
1124 	 * tolerance to a belated transfers. Hence we need to compensate the
1125 	 * memory arbitration imperfection for them in order to prevent FIFO
1126 	 * underflow condition when memory bus is busy.
1127 	 *
1128 	 * VI clients also need a stronger compensation.
1129 	 */
1130 	switch (client->swgroup) {
1131 	case TEGRA_SWGROUP_MPCORE:
1132 	case TEGRA_SWGROUP_PTC:
1133 		/*
1134 		 * We always want lower latency for these clients, hence
1135 		 * don't touch them.
1136 		 */
1137 		return;
1138 
1139 	case TEGRA_SWGROUP_DC:
1140 	case TEGRA_SWGROUP_DCB:
1141 		arb_tolerance_compensation_nsec = 1050;
1142 		arb_tolerance_compensation_div = 2;
1143 		break;
1144 
1145 	case TEGRA_SWGROUP_VI:
1146 		arb_tolerance_compensation_nsec = 1050;
1147 		arb_tolerance_compensation_div = 1;
1148 		break;
1149 
1150 	default:
1151 		arb_tolerance_compensation_nsec = 150;
1152 		arb_tolerance_compensation_div = 1;
1153 		break;
1154 	}
1155 
1156 	if (arb_nsec > arb_tolerance_compensation_nsec)
1157 		arb_nsec -= arb_tolerance_compensation_nsec;
1158 	else
1159 		arb_nsec = 0;
1160 
1161 	arb_nsec /= arb_tolerance_compensation_div;
1162 
1163 	/*
1164 	 * Latency allowance is a number of ticks a request from a particular
1165 	 * client may wait in the EMEM arbiter before it becomes a high-priority
1166 	 * request.
1167 	 */
1168 	la_ticks = arb_nsec / mc->tick;
1169 	la_ticks = min(la_ticks, client->regs.la.mask);
1170 
1171 	value = mc_readl(mc, client->regs.la.reg);
1172 	value &= ~(client->regs.la.mask << client->regs.la.shift);
1173 	value |= la_ticks << client->regs.la.shift;
1174 	mc_writel(mc, value, client->regs.la.reg);
1175 }
1176 
1177 static int tegra114_mc_icc_set(struct icc_node *src, struct icc_node *dst)
1178 {
1179 	struct tegra_mc *mc = icc_provider_to_tegra_mc(src->provider);
1180 	const struct tegra_mc_client *client = &mc->soc->clients[src->id];
1181 	u64 peak_bandwidth = icc_units_to_bps(src->peak_bw);
1182 
1183 	/*
1184 	 * Skip pre-initialization that is done by icc_node_add(), which sets
1185 	 * bandwidth to maximum for all clients before drivers are loaded.
1186 	 *
1187 	 * This doesn't make sense for us because we don't have drivers for all
1188 	 * clients and it's okay to keep configuration left from bootloader
1189 	 * during boot, at least for today.
1190 	 */
1191 	if (src == dst)
1192 		return 0;
1193 
1194 	/* convert bytes/sec to megabytes/sec */
1195 	do_div(peak_bandwidth, 1000000);
1196 
1197 	tegra114_mc_tune_client_latency(mc, client, peak_bandwidth);
1198 
1199 	return 0;
1200 }
1201 
1202 static int tegra114_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw,
1203 				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
1204 {
1205 	/*
1206 	 * ISO clients need to reserve extra bandwidth up-front because
1207 	 * there could be high bandwidth pressure during initial filling
1208 	 * of the client's FIFO buffers.  Secondly, we need to take into
1209 	 * account impurities of the memory subsystem.
1210 	 */
1211 	if (tag & TEGRA_MC_ICC_TAG_ISO)
1212 		peak_bw = tegra_mc_scale_percents(peak_bw, 400);
1213 
1214 	*agg_avg += avg_bw;
1215 	*agg_peak = max(*agg_peak, peak_bw);
1216 
1217 	return 0;
1218 }
1219 
1220 static struct icc_node_data *
1221 tegra114_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
1222 {
1223 	struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
1224 	const struct tegra_mc_client *client;
1225 	unsigned int i, idx = spec->args[0];
1226 	struct icc_node_data *ndata;
1227 	struct icc_node *node;
1228 
1229 	list_for_each_entry(node, &mc->provider.nodes, node_list) {
1230 		if (node->id != idx)
1231 			continue;
1232 
1233 		ndata = kzalloc_obj(*ndata);
1234 		if (!ndata)
1235 			return ERR_PTR(-ENOMEM);
1236 
1237 		client = &mc->soc->clients[idx];
1238 		ndata->node = node;
1239 
1240 		switch (client->swgroup) {
1241 		case TEGRA_SWGROUP_DC:
1242 		case TEGRA_SWGROUP_DCB:
1243 		case TEGRA_SWGROUP_PTC:
1244 		case TEGRA_SWGROUP_VI:
1245 			/* these clients are isochronous by default */
1246 			ndata->tag = TEGRA_MC_ICC_TAG_ISO;
1247 			break;
1248 
1249 		default:
1250 			ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
1251 			break;
1252 		}
1253 
1254 		return ndata;
1255 	}
1256 
1257 	for (i = 0; i < mc->soc->num_clients; i++) {
1258 		if (mc->soc->clients[i].id == idx)
1259 			return ERR_PTR(-EPROBE_DEFER);
1260 	}
1261 
1262 	dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
1263 
1264 	return ERR_PTR(-EINVAL);
1265 }
1266 
1267 static const struct tegra_mc_icc_ops tegra114_mc_icc_ops = {
1268 	.xlate_extended = tegra114_mc_of_icc_xlate_extended,
1269 	.aggregate = tegra114_mc_icc_aggreate,
1270 	.set = tegra114_mc_icc_set,
1271 };
1272 
1273 static const unsigned long tegra114_mc_emem_regs[] = {
1274 	MC_EMEM_ARB_CFG,
1275 	MC_EMEM_ARB_OUTSTANDING_REQ,
1276 	MC_EMEM_ARB_TIMING_RCD,
1277 	MC_EMEM_ARB_TIMING_RP,
1278 	MC_EMEM_ARB_TIMING_RC,
1279 	MC_EMEM_ARB_TIMING_RAS,
1280 	MC_EMEM_ARB_TIMING_FAW,
1281 	MC_EMEM_ARB_TIMING_RRD,
1282 	MC_EMEM_ARB_TIMING_RAP2PRE,
1283 	MC_EMEM_ARB_TIMING_WAP2PRE,
1284 	MC_EMEM_ARB_TIMING_R2R,
1285 	MC_EMEM_ARB_TIMING_W2W,
1286 	MC_EMEM_ARB_TIMING_R2W,
1287 	MC_EMEM_ARB_TIMING_W2R,
1288 	MC_EMEM_ARB_DA_TURNS,
1289 	MC_EMEM_ARB_DA_COVERS,
1290 	MC_EMEM_ARB_MISC0,
1291 	MC_EMEM_ARB_RING1_THROTTLE,
1292 };
1293 
1294 static const struct tegra_mc_intmask tegra114_mc_intmasks[] = {
1295 	{
1296 		.reg = MC_INTMASK,
1297 		.mask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
1298 			MC_INT_DECERR_EMEM,
1299 	},
1300 };
1301 
1302 const struct tegra_mc_soc tegra114_mc_soc = {
1303 	.clients = tegra114_mc_clients,
1304 	.num_clients = ARRAY_SIZE(tegra114_mc_clients),
1305 	.num_address_bits = 32,
1306 	.atom_size = 32,
1307 	.client_id_mask = 0x7f,
1308 	.smmu = &tegra114_smmu_soc,
1309 	.emem_regs = tegra114_mc_emem_regs,
1310 	.num_emem_regs = ARRAY_SIZE(tegra114_mc_emem_regs),
1311 	.intmasks = tegra114_mc_intmasks,
1312 	.num_intmasks = ARRAY_SIZE(tegra114_mc_intmasks),
1313 	.reset_ops = &tegra_mc_reset_ops_common,
1314 	.resets = tegra114_mc_resets,
1315 	.num_resets = ARRAY_SIZE(tegra114_mc_resets),
1316 	.icc_ops = &tegra114_mc_icc_ops,
1317 	.ops = &tegra30_mc_ops,
1318 	.regs = &tegra20_mc_regs,
1319 	.handle_irq = tegra30_mc_irq_handlers,
1320 	.num_interrupts = ARRAY_SIZE(tegra30_mc_irq_handlers),
1321 	.mc_err_status_type_mask = (0x7 << 28),
1322 };
1323