1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2014 NVIDIA CORPORATION.  All rights reserved.
4 */
5
6#include <linux/device.h>
7#include <linux/of.h>
8#include <linux/slab.h>
9
10#include <dt-bindings/memory/tegra30-mc.h>
11
12#include "mc.h"
13
14static 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
35static 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
1141static 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
1160static 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
1168static 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
1176static 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
1198static 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
1219static 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
1291static 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
1316static 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
1334static struct icc_node_data *
1335tegra30_mc_of_icc_xlate_extended(const 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
1381static 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
1387const 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