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