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