GNU Linux-libre 5.13.14-gnu1
[releases.git] / drivers / memory / tegra / tegra30.c
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
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
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
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 *
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 };