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