aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memory/tegra
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-04-16 03:24:44 -0400
committerThierry Reding <treding@nvidia.com>2014-12-04 10:11:47 -0500
commit8918465163171322c77a19d5258a95f56d89d2e4 (patch)
tree4d818b6d61af15bffc6c60316c7b5d64efb01bde /drivers/memory/tegra
parent4bc567dd60a1cfa9abd8484cff2de31cdf51649d (diff)
memory: Add NVIDIA Tegra memory controller support
The memory controller on NVIDIA Tegra exposes various knobs that can be used to tune the behaviour of the clients attached to it. Currently this driver sets up the latency allowance registers to the HW defaults. Eventually an API should be exported by this driver (via a custom API or a generic subsystem) to allow clients to register latency requirements. This driver also registers an IOMMU (SMMU) that's implemented by the memory controller. It is supported on Tegra30, Tegra114 and Tegra124 currently. Tegra20 has a GART instead. The Tegra SMMU operates on memory clients and SWGROUPs. A memory client is a unidirectional, special-purpose DMA master. A SWGROUP represents a set of memory clients that form a logical functional unit corresponding to a single device. Typically a device has two clients: one client for read transactions and one client for write transactions, but there are also devices that have only read clients, but many of them (such as the display controllers). Because there is no 1:1 relationship between memory clients and devices the driver keeps a table of memory clients and the SWGROUPs that they belong to per SoC. Note that this is an exception and due to the fact that the SMMU is tightly integrated with the rest of the Tegra SoC. The use of these tables is discouraged in drivers for generic IOMMU devices such as the ARM SMMU because the same IOMMU could be used in any number of SoCs and keeping such tables for each SoC would not scale. Acked-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/memory/tegra')
-rw-r--r--drivers/memory/tegra/Kconfig7
-rw-r--r--drivers/memory/tegra/Makefile7
-rw-r--r--drivers/memory/tegra/mc.c301
-rw-r--r--drivers/memory/tegra/mc.h40
-rw-r--r--drivers/memory/tegra/tegra114.c948
-rw-r--r--drivers/memory/tegra/tegra124.c995
-rw-r--r--drivers/memory/tegra/tegra30.c970
7 files changed, 3268 insertions, 0 deletions
diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
new file mode 100644
index 000000000000..571087621827
--- /dev/null
+++ b/drivers/memory/tegra/Kconfig
@@ -0,0 +1,7 @@
1config TEGRA_MC
2 bool "NVIDIA Tegra Memory Controller support"
3 default y
4 depends on ARCH_TEGRA
5 help
6 This driver supports the Memory Controller (MC) hardware found on
7 NVIDIA Tegra SoCs.
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
new file mode 100644
index 000000000000..0d9f497b786c
--- /dev/null
+++ b/drivers/memory/tegra/Makefile
@@ -0,0 +1,7 @@
1tegra-mc-y := mc.o
2
3tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o
4tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o
5tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o
6
7obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
new file mode 100644
index 000000000000..fe3c44e7e1d1
--- /dev/null
+++ b/drivers/memory/tegra/mc.c
@@ -0,0 +1,301 @@
1/*
2 * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/interrupt.h>
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16
17#include "mc.h"
18
19#define MC_INTSTATUS 0x000
20#define MC_INT_DECERR_MTS (1 << 16)
21#define MC_INT_SECERR_SEC (1 << 13)
22#define MC_INT_DECERR_VPR (1 << 12)
23#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11)
24#define MC_INT_INVALID_SMMU_PAGE (1 << 10)
25#define MC_INT_ARBITRATION_EMEM (1 << 9)
26#define MC_INT_SECURITY_VIOLATION (1 << 8)
27#define MC_INT_DECERR_EMEM (1 << 6)
28
29#define MC_INTMASK 0x004
30
31#define MC_ERR_STATUS 0x08
32#define MC_ERR_STATUS_TYPE_SHIFT 28
33#define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (6 << MC_ERR_STATUS_TYPE_SHIFT)
34#define MC_ERR_STATUS_TYPE_MASK (0x7 << MC_ERR_STATUS_TYPE_SHIFT)
35#define MC_ERR_STATUS_READABLE (1 << 27)
36#define MC_ERR_STATUS_WRITABLE (1 << 26)
37#define MC_ERR_STATUS_NONSECURE (1 << 25)
38#define MC_ERR_STATUS_ADR_HI_SHIFT 20
39#define MC_ERR_STATUS_ADR_HI_MASK 0x3
40#define MC_ERR_STATUS_SECURITY (1 << 17)
41#define MC_ERR_STATUS_RW (1 << 16)
42#define MC_ERR_STATUS_CLIENT_MASK 0x7f
43
44#define MC_ERR_ADR 0x0c
45
46#define MC_EMEM_ARB_CFG 0x90
47#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) (((x) & 0x1ff) << 0)
48#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
49#define MC_EMEM_ARB_MISC0 0xd8
50
51static const struct of_device_id tegra_mc_of_match[] = {
52#ifdef CONFIG_ARCH_TEGRA_3x_SOC
53 { .compatible = "nvidia,tegra30-mc", .data = &tegra30_mc_soc },
54#endif
55#ifdef CONFIG_ARCH_TEGRA_114_SOC
56 { .compatible = "nvidia,tegra114-mc", .data = &tegra114_mc_soc },
57#endif
58#ifdef CONFIG_ARCH_TEGRA_124_SOC
59 { .compatible = "nvidia,tegra124-mc", .data = &tegra124_mc_soc },
60#endif
61 { }
62};
63MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
64
65static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
66{
67 unsigned long long tick;
68 unsigned int i;
69 u32 value;
70
71 /* compute the number of MC clock cycles per tick */
72 tick = mc->tick * clk_get_rate(mc->clk);
73 do_div(tick, NSEC_PER_SEC);
74
75 value = readl(mc->regs + MC_EMEM_ARB_CFG);
76 value &= ~MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK;
77 value |= MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(tick);
78 writel(value, mc->regs + MC_EMEM_ARB_CFG);
79
80 /* write latency allowance defaults */
81 for (i = 0; i < mc->soc->num_clients; i++) {
82 const struct tegra_mc_la *la = &mc->soc->clients[i].la;
83 u32 value;
84
85 value = readl(mc->regs + la->reg);
86 value &= ~(la->mask << la->shift);
87 value |= (la->def & la->mask) << la->shift;
88 writel(value, mc->regs + la->reg);
89 }
90
91 return 0;
92}
93
94static const char *const status_names[32] = {
95 [ 1] = "External interrupt",
96 [ 6] = "EMEM address decode error",
97 [ 8] = "Security violation",
98 [ 9] = "EMEM arbitration error",
99 [10] = "Page fault",
100 [11] = "Invalid APB ASID update",
101 [12] = "VPR violation",
102 [13] = "Secure carveout violation",
103 [16] = "MTS carveout violation",
104};
105
106static const char *const error_names[8] = {
107 [2] = "EMEM decode error",
108 [3] = "TrustZone violation",
109 [4] = "Carveout violation",
110 [6] = "SMMU translation error",
111};
112
113static irqreturn_t tegra_mc_irq(int irq, void *data)
114{
115 struct tegra_mc *mc = data;
116 unsigned long status, mask;
117 unsigned int bit;
118
119 /* mask all interrupts to avoid flooding */
120 status = mc_readl(mc, MC_INTSTATUS);
121 mask = mc_readl(mc, MC_INTMASK);
122
123 for_each_set_bit(bit, &status, 32) {
124 const char *error = status_names[bit] ?: "unknown";
125 const char *client = "unknown", *desc;
126 const char *direction, *secure;
127 phys_addr_t addr = 0;
128 unsigned int i;
129 char perm[7];
130 u8 id, type;
131 u32 value;
132
133 value = mc_readl(mc, MC_ERR_STATUS);
134
135#ifdef CONFIG_PHYS_ADDR_T_64BIT
136 if (mc->soc->num_address_bits > 32) {
137 addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) &
138 MC_ERR_STATUS_ADR_HI_MASK);
139 addr <<= 32;
140 }
141#endif
142
143 if (value & MC_ERR_STATUS_RW)
144 direction = "write";
145 else
146 direction = "read";
147
148 if (value & MC_ERR_STATUS_SECURITY)
149 secure = "secure ";
150 else
151 secure = "";
152
153 id = value & MC_ERR_STATUS_CLIENT_MASK;
154
155 for (i = 0; i < mc->soc->num_clients; i++) {
156 if (mc->soc->clients[i].id == id) {
157 client = mc->soc->clients[i].name;
158 break;
159 }
160 }
161
162 type = (value & MC_ERR_STATUS_TYPE_MASK) >>
163 MC_ERR_STATUS_TYPE_SHIFT;
164 desc = error_names[type];
165
166 switch (value & MC_ERR_STATUS_TYPE_MASK) {
167 case MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE:
168 perm[0] = ' ';
169 perm[1] = '[';
170
171 if (value & MC_ERR_STATUS_READABLE)
172 perm[2] = 'R';
173 else
174 perm[2] = '-';
175
176 if (value & MC_ERR_STATUS_WRITABLE)
177 perm[3] = 'W';
178 else
179 perm[3] = '-';
180
181 if (value & MC_ERR_STATUS_NONSECURE)
182 perm[4] = '-';
183 else
184 perm[4] = 'S';
185
186 perm[5] = ']';
187 perm[6] = '\0';
188 break;
189
190 default:
191 perm[0] = '\0';
192 break;
193 }
194
195 value = mc_readl(mc, MC_ERR_ADR);
196 addr |= value;
197
198 dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s%s)\n",
199 client, secure, direction, &addr, error,
200 desc, perm);
201 }
202
203 /* clear interrupts */
204 mc_writel(mc, status, MC_INTSTATUS);
205
206 return IRQ_HANDLED;
207}
208
209static int tegra_mc_probe(struct platform_device *pdev)
210{
211 const struct of_device_id *match;
212 struct resource *res;
213 struct tegra_mc *mc;
214 u32 value;
215 int err;
216
217 match = of_match_node(tegra_mc_of_match, pdev->dev.of_node);
218 if (!match)
219 return -ENODEV;
220
221 mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
222 if (!mc)
223 return -ENOMEM;
224
225 platform_set_drvdata(pdev, mc);
226 mc->soc = match->data;
227 mc->dev = &pdev->dev;
228
229 /* length of MC tick in nanoseconds */
230 mc->tick = 30;
231
232 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
233 mc->regs = devm_ioremap_resource(&pdev->dev, res);
234 if (IS_ERR(mc->regs))
235 return PTR_ERR(mc->regs);
236
237 mc->clk = devm_clk_get(&pdev->dev, "mc");
238 if (IS_ERR(mc->clk)) {
239 dev_err(&pdev->dev, "failed to get MC clock: %ld\n",
240 PTR_ERR(mc->clk));
241 return PTR_ERR(mc->clk);
242 }
243
244 err = tegra_mc_setup_latency_allowance(mc);
245 if (err < 0) {
246 dev_err(&pdev->dev, "failed to setup latency allowance: %d\n",
247 err);
248 return err;
249 }
250
251 if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
252 mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
253 if (IS_ERR(mc->smmu)) {
254 dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
255 PTR_ERR(mc->smmu));
256 return PTR_ERR(mc->smmu);
257 }
258 }
259
260 mc->irq = platform_get_irq(pdev, 0);
261 if (mc->irq < 0) {
262 dev_err(&pdev->dev, "interrupt not specified\n");
263 return mc->irq;
264 }
265
266 err = devm_request_irq(&pdev->dev, mc->irq, tegra_mc_irq, IRQF_SHARED,
267 dev_name(&pdev->dev), mc);
268 if (err < 0) {
269 dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq,
270 err);
271 return err;
272 }
273
274 value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
275 MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
276 MC_INT_ARBITRATION_EMEM | MC_INT_SECURITY_VIOLATION |
277 MC_INT_DECERR_EMEM;
278 mc_writel(mc, value, MC_INTMASK);
279
280 return 0;
281}
282
283static struct platform_driver tegra_mc_driver = {
284 .driver = {
285 .name = "tegra-mc",
286 .of_match_table = tegra_mc_of_match,
287 .suppress_bind_attrs = true,
288 },
289 .prevent_deferred_probe = true,
290 .probe = tegra_mc_probe,
291};
292
293static int tegra_mc_init(void)
294{
295 return platform_driver_register(&tegra_mc_driver);
296}
297arch_initcall(tegra_mc_init);
298
299MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
300MODULE_DESCRIPTION("NVIDIA Tegra Memory Controller driver");
301MODULE_LICENSE("GPL v2");
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
new file mode 100644
index 000000000000..d5d21147fc77
--- /dev/null
+++ b/drivers/memory/tegra/mc.h
@@ -0,0 +1,40 @@
1/*
2 * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef MEMORY_TEGRA_MC_H
10#define MEMORY_TEGRA_MC_H
11
12#include <linux/io.h>
13#include <linux/types.h>
14
15#include <soc/tegra/mc.h>
16
17static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset)
18{
19 return readl(mc->regs + offset);
20}
21
22static inline void mc_writel(struct tegra_mc *mc, u32 value,
23 unsigned long offset)
24{
25 writel(value, mc->regs + offset);
26}
27
28#ifdef CONFIG_ARCH_TEGRA_3x_SOC
29extern const struct tegra_mc_soc tegra30_mc_soc;
30#endif
31
32#ifdef CONFIG_ARCH_TEGRA_114_SOC
33extern const struct tegra_mc_soc tegra114_mc_soc;
34#endif
35
36#ifdef CONFIG_ARCH_TEGRA_124_SOC
37extern const struct tegra_mc_soc tegra124_mc_soc;
38#endif
39
40#endif /* MEMORY_TEGRA_MC_H */
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c
new file mode 100644
index 000000000000..511e9a25c151
--- /dev/null
+++ b/drivers/memory/tegra/tegra114.c
@@ -0,0 +1,948 @@
1/*
2 * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/of.h>
10#include <linux/mm.h>
11
12#include <asm/cacheflush.h>
13
14#include <dt-bindings/memory/tegra114-mc.h>
15
16#include "mc.h"
17
18static const struct tegra_mc_client tegra114_mc_clients[] = {
19 {
20 .id = 0x00,
21 .name = "ptcr",
22 .swgroup = TEGRA_SWGROUP_PTC,
23 }, {
24 .id = 0x01,
25 .name = "display0a",
26 .swgroup = TEGRA_SWGROUP_DC,
27 .smmu = {
28 .reg = 0x228,
29 .bit = 1,
30 },
31 .la = {
32 .reg = 0x2e8,
33 .shift = 0,
34 .mask = 0xff,
35 .def = 0x4e,
36 },
37 }, {
38 .id = 0x02,
39 .name = "display0ab",
40 .swgroup = TEGRA_SWGROUP_DCB,
41 .smmu = {
42 .reg = 0x228,
43 .bit = 2,
44 },
45 .la = {
46 .reg = 0x2f4,
47 .shift = 0,
48 .mask = 0xff,
49 .def = 0x4e,
50 },
51 }, {
52 .id = 0x03,
53 .name = "display0b",
54 .swgroup = TEGRA_SWGROUP_DC,
55 .smmu = {
56 .reg = 0x228,
57 .bit = 3,
58 },
59 .la = {
60 .reg = 0x2e8,
61 .shift = 16,
62 .mask = 0xff,
63 .def = 0x4e,
64 },
65 }, {
66 .id = 0x04,
67 .name = "display0bb",
68 .swgroup = TEGRA_SWGROUP_DCB,
69 .smmu = {
70 .reg = 0x228,
71 .bit = 4,
72 },
73 .la = {
74 .reg = 0x2f4,
75 .shift = 16,
76 .mask = 0xff,
77 .def = 0x4e,
78 },
79 }, {
80 .id = 0x05,
81 .name = "display0c",
82 .swgroup = TEGRA_SWGROUP_DC,
83 .smmu = {
84 .reg = 0x228,
85 .bit = 5,
86 },
87 .la = {
88 .reg = 0x2ec,
89 .shift = 0,
90 .mask = 0xff,
91 .def = 0x4e,
92 },
93 }, {
94 .id = 0x06,
95 .name = "display0cb",
96 .swgroup = TEGRA_SWGROUP_DCB,
97 .smmu = {
98 .reg = 0x228,
99 .bit = 6,
100 },
101 .la = {
102 .reg = 0x2f8,
103 .shift = 0,
104 .mask = 0xff,
105 .def = 0x4e,
106 },
107 }, {
108 .id = 0x09,
109 .name = "eppup",
110 .swgroup = TEGRA_SWGROUP_EPP,
111 .smmu = {
112 .reg = 0x228,
113 .bit = 9,
114 },
115 .la = {
116 .reg = 0x300,
117 .shift = 0,
118 .mask = 0xff,
119 .def = 0x33,
120 },
121 }, {
122 .id = 0x0a,
123 .name = "g2pr",
124 .swgroup = TEGRA_SWGROUP_G2,
125 .smmu = {
126 .reg = 0x228,
127 .bit = 10,
128 },
129 .la = {
130 .reg = 0x308,
131 .shift = 0,
132 .mask = 0xff,
133 .def = 0x09,
134 },
135 }, {
136 .id = 0x0b,
137 .name = "g2sr",
138 .swgroup = TEGRA_SWGROUP_G2,
139 .smmu = {
140 .reg = 0x228,
141 .bit = 11,
142 },
143 .la = {
144 .reg = 0x308,
145 .shift = 16,
146 .mask = 0xff,
147 .def = 0x09,
148 },
149 }, {
150 .id = 0x0f,
151 .name = "avpcarm7r",
152 .swgroup = TEGRA_SWGROUP_AVPC,
153 .smmu = {
154 .reg = 0x228,
155 .bit = 15,
156 },
157 .la = {
158 .reg = 0x2e4,
159 .shift = 0,
160 .mask = 0xff,
161 .def = 0x04,
162 },
163 }, {
164 .id = 0x10,
165 .name = "displayhc",
166 .swgroup = TEGRA_SWGROUP_DC,
167 .smmu = {
168 .reg = 0x228,
169 .bit = 16,
170 },
171 .la = {
172 .reg = 0x2f0,
173 .shift = 0,
174 .mask = 0xff,
175 .def = 0x68,
176 },
177 }, {
178 .id = 0x11,
179 .name = "displayhcb",
180 .swgroup = TEGRA_SWGROUP_DCB,
181 .smmu = {
182 .reg = 0x228,
183 .bit = 17,
184 },
185 .la = {
186 .reg = 0x2fc,
187 .shift = 0,
188 .mask = 0xff,
189 .def = 0x68,
190 },
191 }, {
192 .id = 0x12,
193 .name = "fdcdrd",
194 .swgroup = TEGRA_SWGROUP_NV,
195 .smmu = {
196 .reg = 0x228,
197 .bit = 18,
198 },
199 .la = {
200 .reg = 0x334,
201 .shift = 0,
202 .mask = 0xff,
203 .def = 0x0c,
204 },
205 }, {
206 .id = 0x13,
207 .name = "fdcdrd2",
208 .swgroup = TEGRA_SWGROUP_NV,
209 .smmu = {
210 .reg = 0x228,
211 .bit = 19,
212 },
213 .la = {
214 .reg = 0x33c,
215 .shift = 0,
216 .mask = 0xff,
217 .def = 0x0c,
218 },
219 }, {
220 .id = 0x14,
221 .name = "g2dr",
222 .swgroup = TEGRA_SWGROUP_G2,
223 .smmu = {
224 .reg = 0x228,
225 .bit = 20,
226 },
227 .la = {
228 .reg = 0x30c,
229 .shift = 0,
230 .mask = 0xff,
231 .def = 0x0a,
232 },
233 }, {
234 .id = 0x15,
235 .name = "hdar",
236 .swgroup = TEGRA_SWGROUP_HDA,
237 .smmu = {
238 .reg = 0x228,
239 .bit = 21,
240 },
241 .la = {
242 .reg = 0x318,
243 .shift = 0,
244 .mask = 0xff,
245 .def = 0xff,
246 },
247 }, {
248 .id = 0x16,
249 .name = "host1xdmar",
250 .swgroup = TEGRA_SWGROUP_HC,
251 .smmu = {
252 .reg = 0x228,
253 .bit = 22,
254 },
255 .la = {
256 .reg = 0x310,
257 .shift = 0,
258 .mask = 0xff,
259 .def = 0x10,
260 },
261 }, {
262 .id = 0x17,
263 .name = "host1xr",
264 .swgroup = TEGRA_SWGROUP_HC,
265 .smmu = {
266 .reg = 0x228,
267 .bit = 23,
268 },
269 .la = {
270 .reg = 0x310,
271 .shift = 16,
272 .mask = 0xff,
273 .def = 0xa5,
274 },
275 }, {
276 .id = 0x18,
277 .name = "idxsrd",
278 .swgroup = TEGRA_SWGROUP_NV,
279 .smmu = {
280 .reg = 0x228,
281 .bit = 24,
282 },
283 .la = {
284 .reg = 0x334,
285 .shift = 16,
286 .mask = 0xff,
287 .def = 0x0b,
288 },
289 }, {
290 .id = 0x1c,
291 .name = "msencsrd",
292 .swgroup = TEGRA_SWGROUP_MSENC,
293 .smmu = {
294 .reg = 0x228,
295 .bit = 28,
296 },
297 .la = {
298 .reg = 0x328,
299 .shift = 0,
300 .mask = 0xff,
301 .def = 0x80,
302 },
303 }, {
304 .id = 0x1d,
305 .name = "ppcsahbdmar",
306 .swgroup = TEGRA_SWGROUP_PPCS,
307 .smmu = {
308 .reg = 0x228,
309 .bit = 29,
310 },
311 .la = {
312 .reg = 0x344,
313 .shift = 0,
314 .mask = 0xff,
315 .def = 0x50,
316 },
317 }, {
318 .id = 0x1e,
319 .name = "ppcsahbslvr",
320 .swgroup = TEGRA_SWGROUP_PPCS,
321 .smmu = {
322 .reg = 0x228,
323 .bit = 30,
324 },
325 .la = {
326 .reg = 0x344,
327 .shift = 16,
328 .mask = 0xff,
329 .def = 0xe8,
330 },
331 }, {
332 .id = 0x20,
333 .name = "texl2srd",
334 .swgroup = TEGRA_SWGROUP_NV,
335 .smmu = {
336 .reg = 0x22c,
337 .bit = 0,
338 },
339 .la = {
340 .reg = 0x338,
341 .shift = 0,
342 .mask = 0xff,
343 .def = 0x0c,
344 },
345 }, {
346 .id = 0x22,
347 .name = "vdebsevr",
348 .swgroup = TEGRA_SWGROUP_VDE,
349 .smmu = {
350 .reg = 0x22c,
351 .bit = 2,
352 },
353 .la = {
354 .reg = 0x354,
355 .shift = 0,
356 .mask = 0xff,
357 .def = 0xff,
358 },
359 }, {
360 .id = 0x23,
361 .name = "vdember",
362 .swgroup = TEGRA_SWGROUP_VDE,
363 .smmu = {
364 .reg = 0x22c,
365 .bit = 3,
366 },
367 .la = {
368 .reg = 0x354,
369 .shift = 16,
370 .mask = 0xff,
371 .def = 0xff,
372 },
373 }, {
374 .id = 0x24,
375 .name = "vdemcer",
376 .swgroup = TEGRA_SWGROUP_VDE,
377 .smmu = {
378 .reg = 0x22c,
379 .bit = 4,
380 },
381 .la = {
382 .reg = 0x358,
383 .shift = 0,
384 .mask = 0xff,
385 .def = 0xb8,
386 },
387 }, {
388 .id = 0x25,
389 .name = "vdetper",
390 .swgroup = TEGRA_SWGROUP_VDE,
391 .smmu = {
392 .reg = 0x22c,
393 .bit = 5,
394 },
395 .la = {
396 .reg = 0x358,
397 .shift = 16,
398 .mask = 0xff,
399 .def = 0xee,
400 },
401 }, {
402 .id = 0x26,
403 .name = "mpcorelpr",
404 .swgroup = TEGRA_SWGROUP_MPCORELP,
405 .la = {
406 .reg = 0x324,
407 .shift = 0,
408 .mask = 0xff,
409 .def = 0x04,
410 },
411 }, {
412 .id = 0x27,
413 .name = "mpcorer",
414 .swgroup = TEGRA_SWGROUP_MPCORE,
415 .la = {
416 .reg = 0x320,
417 .shift = 0,
418 .mask = 0xff,
419 .def = 0x04,
420 },
421 }, {
422 .id = 0x28,
423 .name = "eppu",
424 .swgroup = TEGRA_SWGROUP_EPP,
425 .smmu = {
426 .reg = 0x22c,
427 .bit = 8,
428 },
429 .la = {
430 .reg = 0x300,
431 .shift = 16,
432 .mask = 0xff,
433 .def = 0x33,
434 },
435 }, {
436 .id = 0x29,
437 .name = "eppv",
438 .swgroup = TEGRA_SWGROUP_EPP,
439 .smmu = {
440 .reg = 0x22c,
441 .bit = 9,
442 },
443 .la = {
444 .reg = 0x304,
445 .shift = 0,
446 .mask = 0xff,
447 .def = 0x6c,
448 },
449 }, {
450 .id = 0x2a,
451 .name = "eppy",
452 .swgroup = TEGRA_SWGROUP_EPP,
453 .smmu = {
454 .reg = 0x22c,
455 .bit = 10,
456 },
457 .la = {
458 .reg = 0x304,
459 .shift = 16,
460 .mask = 0xff,
461 .def = 0x6c,
462 },
463 }, {
464 .id = 0x2b,
465 .name = "msencswr",
466 .swgroup = TEGRA_SWGROUP_MSENC,
467 .smmu = {
468 .reg = 0x22c,
469 .bit = 11,
470 },
471 .la = {
472 .reg = 0x328,
473 .shift = 16,
474 .mask = 0xff,
475 .def = 0x80,
476 },
477 }, {
478 .id = 0x2c,
479 .name = "viwsb",
480 .swgroup = TEGRA_SWGROUP_VI,
481 .smmu = {
482 .reg = 0x22c,
483 .bit = 12,
484 },
485 .la = {
486 .reg = 0x364,
487 .shift = 0,
488 .mask = 0xff,
489 .def = 0x47,
490 },
491 }, {
492 .id = 0x2d,
493 .name = "viwu",
494 .swgroup = TEGRA_SWGROUP_VI,
495 .smmu = {
496 .reg = 0x22c,
497 .bit = 13,
498 },
499 .la = {
500 .reg = 0x368,
501 .shift = 0,
502 .mask = 0xff,
503 .def = 0xff,
504 },
505 }, {
506 .id = 0x2e,
507 .name = "viwv",
508 .swgroup = TEGRA_SWGROUP_VI,
509 .smmu = {
510 .reg = 0x22c,
511 .bit = 14,
512 },
513 .la = {
514 .reg = 0x368,
515 .shift = 16,
516 .mask = 0xff,
517 .def = 0xff,
518 },
519 }, {
520 .id = 0x2f,
521 .name = "viwy",
522 .swgroup = TEGRA_SWGROUP_VI,
523 .smmu = {
524 .reg = 0x22c,
525 .bit = 15,
526 },
527 .la = {
528 .reg = 0x36c,
529 .shift = 0,
530 .mask = 0xff,
531 .def = 0x47,
532 },
533 }, {
534 .id = 0x30,
535 .name = "g2dw",
536 .swgroup = TEGRA_SWGROUP_G2,
537 .smmu = {
538 .reg = 0x22c,
539 .bit = 16,
540 },
541 .la = {
542 .reg = 0x30c,
543 .shift = 16,
544 .mask = 0xff,
545 .def = 0x9,
546 },
547 }, {
548 .id = 0x32,
549 .name = "avpcarm7w",
550 .swgroup = TEGRA_SWGROUP_AVPC,
551 .smmu = {
552 .reg = 0x22c,
553 .bit = 18,
554 },
555 .la = {
556 .reg = 0x2e4,
557 .shift = 16,
558 .mask = 0xff,
559 .def = 0x0e,
560 },
561 }, {
562 .id = 0x33,
563 .name = "fdcdwr",
564 .swgroup = TEGRA_SWGROUP_NV,
565 .smmu = {
566 .reg = 0x22c,
567 .bit = 19,
568 },
569 .la = {
570 .reg = 0x338,
571 .shift = 16,
572 .mask = 0xff,
573 .def = 0x10,
574 },
575 }, {
576 .id = 0x34,
577 .name = "fdcwr2",
578 .swgroup = TEGRA_SWGROUP_NV,
579 .smmu = {
580 .reg = 0x22c,
581 .bit = 20,
582 },
583 .la = {
584 .reg = 0x340,
585 .shift = 0,
586 .mask = 0xff,
587 .def = 0x10,
588 },
589 }, {
590 .id = 0x35,
591 .name = "hdaw",
592 .swgroup = TEGRA_SWGROUP_HDA,
593 .smmu = {
594 .reg = 0x22c,
595 .bit = 21,
596 },
597 .la = {
598 .reg = 0x318,
599 .shift = 16,
600 .mask = 0xff,
601 .def = 0xff,
602 },
603 }, {
604 .id = 0x36,
605 .name = "host1xw",
606 .swgroup = TEGRA_SWGROUP_HC,
607 .smmu = {
608 .reg = 0x22c,
609 .bit = 22,
610 },
611 .la = {
612 .reg = 0x314,
613 .shift = 0,
614 .mask = 0xff,
615 .def = 0x25,
616 },
617 }, {
618 .id = 0x37,
619 .name = "ispw",
620 .swgroup = TEGRA_SWGROUP_ISP,
621 .smmu = {
622 .reg = 0x22c,
623 .bit = 23,
624 },
625 .la = {
626 .reg = 0x31c,
627 .shift = 0,
628 .mask = 0xff,
629 .def = 0xff,
630 },
631 }, {
632 .id = 0x38,
633 .name = "mpcorelpw",
634 .swgroup = TEGRA_SWGROUP_MPCORELP,
635 .la = {
636 .reg = 0x324,
637 .shift = 16,
638 .mask = 0xff,
639 .def = 0x80,
640 },
641 }, {
642 .id = 0x39,
643 .name = "mpcorew",
644 .swgroup = TEGRA_SWGROUP_MPCORE,
645 .la = {
646 .reg = 0x320,
647 .shift = 16,
648 .mask = 0xff,
649 .def = 0x0e,
650 },
651 }, {
652 .id = 0x3b,
653 .name = "ppcsahbdmaw",
654 .swgroup = TEGRA_SWGROUP_PPCS,
655 .smmu = {
656 .reg = 0x22c,
657 .bit = 27,
658 },
659 .la = {
660 .reg = 0x348,
661 .shift = 0,
662 .mask = 0xff,
663 .def = 0xa5,
664 },
665 }, {
666 .id = 0x3c,
667 .name = "ppcsahbslvw",
668 .swgroup = TEGRA_SWGROUP_PPCS,
669 .smmu = {
670 .reg = 0x22c,
671 .bit = 28,
672 },
673 .la = {
674 .reg = 0x348,
675 .shift = 16,
676 .mask = 0xff,
677 .def = 0xe8,
678 },
679 }, {
680 .id = 0x3e,
681 .name = "vdebsevw",
682 .swgroup = TEGRA_SWGROUP_VDE,
683 .smmu = {
684 .reg = 0x22c,
685 .bit = 30,
686 },
687 .la = {
688 .reg = 0x35c,
689 .shift = 0,
690 .mask = 0xff,
691 .def = 0xff,
692 },
693 }, {
694 .id = 0x3f,
695 .name = "vdedbgw",
696 .swgroup = TEGRA_SWGROUP_VDE,
697 .smmu = {
698 .reg = 0x22c,
699 .bit = 31,
700 },
701 .la = {
702 .reg = 0x35c,
703 .shift = 16,
704 .mask = 0xff,
705 .def = 0xff,
706 },
707 }, {
708 .id = 0x40,
709 .name = "vdembew",
710 .swgroup = TEGRA_SWGROUP_VDE,
711 .smmu = {
712 .reg = 0x230,
713 .bit = 0,
714 },
715 .la = {
716 .reg = 0x360,
717 .shift = 0,
718 .mask = 0xff,
719 .def = 0x89,
720 },
721 }, {
722 .id = 0x41,
723 .name = "vdetpmw",
724 .swgroup = TEGRA_SWGROUP_VDE,
725 .smmu = {
726 .reg = 0x230,
727 .bit = 1,
728 },
729 .la = {
730 .reg = 0x360,
731 .shift = 16,
732 .mask = 0xff,
733 .def = 0x59,
734 },
735 }, {
736 .id = 0x4a,
737 .name = "xusb_hostr",
738 .swgroup = TEGRA_SWGROUP_XUSB_HOST,
739 .smmu = {
740 .reg = 0x230,
741 .bit = 10,
742 },
743 .la = {
744 .reg = 0x37c,
745 .shift = 0,
746 .mask = 0xff,
747 .def = 0xa5,
748 },
749 }, {
750 .id = 0x4b,
751 .name = "xusb_hostw",
752 .swgroup = TEGRA_SWGROUP_XUSB_HOST,
753 .smmu = {
754 .reg = 0x230,
755 .bit = 11,
756 },
757 .la = {
758 .reg = 0x37c,
759 .shift = 16,
760 .mask = 0xff,
761 .def = 0xa5,
762 },
763 }, {
764 .id = 0x4c,
765 .name = "xusb_devr",
766 .swgroup = TEGRA_SWGROUP_XUSB_DEV,
767 .smmu = {
768 .reg = 0x230,
769 .bit = 12,
770 },
771 .la = {
772 .reg = 0x380,
773 .shift = 0,
774 .mask = 0xff,
775 .def = 0xa5,
776 },
777 }, {
778 .id = 0x4d,
779 .name = "xusb_devw",
780 .swgroup = TEGRA_SWGROUP_XUSB_DEV,
781 .smmu = {
782 .reg = 0x230,
783 .bit = 13,
784 },
785 .la = {
786 .reg = 0x380,
787 .shift = 16,
788 .mask = 0xff,
789 .def = 0xa5,
790 },
791 }, {
792 .id = 0x4e,
793 .name = "fdcdwr3",
794 .swgroup = TEGRA_SWGROUP_NV,
795 .smmu = {
796 .reg = 0x230,
797 .bit = 14,
798 },
799 .la = {
800 .reg = 0x388,
801 .shift = 0,
802 .mask = 0xff,
803 .def = 0x10,
804 },
805 }, {
806 .id = 0x4f,
807 .name = "fdcdrd3",
808 .swgroup = TEGRA_SWGROUP_NV,
809 .smmu = {
810 .reg = 0x230,
811 .bit = 15,
812 },
813 .la = {
814 .reg = 0x384,
815 .shift = 0,
816 .mask = 0xff,
817 .def = 0x0c,
818 },
819 }, {
820 .id = 0x50,
821 .name = "fdcwr4",
822 .swgroup = TEGRA_SWGROUP_NV,
823 .smmu = {
824 .reg = 0x230,
825 .bit = 16,
826 },
827 .la = {
828 .reg = 0x388,
829 .shift = 16,
830 .mask = 0xff,
831 .def = 0x10,
832 },
833 }, {
834 .id = 0x51,
835 .name = "fdcrd4",
836 .swgroup = TEGRA_SWGROUP_NV,
837 .smmu = {
838 .reg = 0x230,
839 .bit = 17,
840 },
841 .la = {
842 .reg = 0x384,
843 .shift = 16,
844 .mask = 0xff,
845 .def = 0x0c,
846 },
847 }, {
848 .id = 0x52,
849 .name = "emucifr",
850 .swgroup = TEGRA_SWGROUP_EMUCIF,
851 .la = {
852 .reg = 0x38c,
853 .shift = 0,
854 .mask = 0xff,
855 .def = 0x04,
856 },
857 }, {
858 .id = 0x53,
859 .name = "emucifw",
860 .swgroup = TEGRA_SWGROUP_EMUCIF,
861 .la = {
862 .reg = 0x38c,
863 .shift = 16,
864 .mask = 0xff,
865 .def = 0x0e,
866 },
867 }, {
868 .id = 0x54,
869 .name = "tsecsrd",
870 .swgroup = TEGRA_SWGROUP_TSEC,
871 .smmu = {
872 .reg = 0x230,
873 .bit = 20,
874 },
875 .la = {
876 .reg = 0x390,
877 .shift = 0,
878 .mask = 0xff,
879 .def = 0x50,
880 },
881 }, {
882 .id = 0x55,
883 .name = "tsecswr",
884 .swgroup = TEGRA_SWGROUP_TSEC,
885 .smmu = {
886 .reg = 0x230,
887 .bit = 21,
888 },
889 .la = {
890 .reg = 0x390,
891 .shift = 16,
892 .mask = 0xff,
893 .def = 0x50,
894 },
895 },
896};
897
898static const struct tegra_smmu_swgroup tegra114_swgroups[] = {
899 { .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 },
900 { .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 },
901 { .swgroup = TEGRA_SWGROUP_EPP, .reg = 0x248 },
902 { .swgroup = TEGRA_SWGROUP_G2, .reg = 0x24c },
903 { .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c },
904 { .swgroup = TEGRA_SWGROUP_NV, .reg = 0x268 },
905 { .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 },
906 { .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 },
907 { .swgroup = TEGRA_SWGROUP_MSENC, .reg = 0x264 },
908 { .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 },
909 { .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c },
910 { .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 },
911 { .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 },
912 { .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 },
913 { .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c },
914 { .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 },
915};
916
917static void tegra114_flush_dcache(struct page *page, unsigned long offset,
918 size_t size)
919{
920 phys_addr_t phys = page_to_phys(page) + offset;
921 void *virt = page_address(page) + offset;
922
923 __cpuc_flush_dcache_area(virt, size);
924 outer_flush_range(phys, phys + size);
925}
926
927static const struct tegra_smmu_ops tegra114_smmu_ops = {
928 .flush_dcache = tegra114_flush_dcache,
929};
930
931static const struct tegra_smmu_soc tegra114_smmu_soc = {
932 .clients = tegra114_mc_clients,
933 .num_clients = ARRAY_SIZE(tegra114_mc_clients),
934 .swgroups = tegra114_swgroups,
935 .num_swgroups = ARRAY_SIZE(tegra114_swgroups),
936 .supports_round_robin_arbitration = false,
937 .supports_request_limit = false,
938 .num_asids = 4,
939 .ops = &tegra114_smmu_ops,
940};
941
942const struct tegra_mc_soc tegra114_mc_soc = {
943 .clients = tegra114_mc_clients,
944 .num_clients = ARRAY_SIZE(tegra114_mc_clients),
945 .num_address_bits = 32,
946 .atom_size = 32,
947 .smmu = &tegra114_smmu_soc,
948};
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
new file mode 100644
index 000000000000..278d40b854c1
--- /dev/null
+++ b/drivers/memory/tegra/tegra124.c
@@ -0,0 +1,995 @@
1/*
2 * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/of.h>
10#include <linux/mm.h>
11
12#include <asm/cacheflush.h>
13
14#include <dt-bindings/memory/tegra124-mc.h>
15
16#include "mc.h"
17
18static const struct tegra_mc_client tegra124_mc_clients[] = {
19 {
20 .id = 0x00,
21 .name = "ptcr",
22 .swgroup = TEGRA_SWGROUP_PTC,
23 }, {
24 .id = 0x01,
25 .name = "display0a",
26 .swgroup = TEGRA_SWGROUP_DC,
27 .smmu = {
28 .reg = 0x228,
29 .bit = 1,
30 },
31 .la = {
32 .reg = 0x2e8,
33 .shift = 0,
34 .mask = 0xff,
35 .def = 0xc2,
36 },
37 }, {
38 .id = 0x02,
39 .name = "display0ab",
40 .swgroup = TEGRA_SWGROUP_DCB,
41 .smmu = {
42 .reg = 0x228,
43 .bit = 2,
44 },
45 .la = {
46 .reg = 0x2f4,
47 .shift = 0,
48 .mask = 0xff,
49 .def = 0xc6,
50 },
51 }, {
52 .id = 0x03,
53 .name = "display0b",
54 .swgroup = TEGRA_SWGROUP_DC,
55 .smmu = {
56 .reg = 0x228,
57 .bit = 3,
58 },
59 .la = {
60 .reg = 0x2e8,
61 .shift = 16,
62 .mask = 0xff,
63 .def = 0x50,
64 },
65 }, {
66 .id = 0x04,
67 .name = "display0bb",
68 .swgroup = TEGRA_SWGROUP_DCB,
69 .smmu = {
70 .reg = 0x228,
71 .bit = 4,
72 },
73 .la = {
74 .reg = 0x2f4,
75 .shift = 16,
76 .mask = 0xff,
77 .def = 0x50,
78 },
79 }, {
80 .id = 0x05,
81 .name = "display0c",
82 .swgroup = TEGRA_SWGROUP_DC,
83 .smmu = {
84 .reg = 0x228,
85 .bit = 5,
86 },
87 .la = {
88 .reg = 0x2ec,
89 .shift = 0,
90 .mask = 0xff,
91 .def = 0x50,
92 },
93 }, {
94 .id = 0x06,
95 .name = "display0cb",
96 .swgroup = TEGRA_SWGROUP_DCB,
97 .smmu = {
98 .reg = 0x228,
99 .bit = 6,
100 },
101 .la = {
102 .reg = 0x2f8,
103 .shift = 0,
104 .mask = 0xff,
105 .def = 0x50,
106 },
107 }, {
108 .id = 0x0e,
109 .name = "afir",
110 .swgroup = TEGRA_SWGROUP_AFI,
111 .smmu = {
112 .reg = 0x228,
113 .bit = 14,
114 },
115 .la = {
116 .reg = 0x2e0,
117 .shift = 0,
118 .mask = 0xff,
119 .def = 0x13,
120 },
121 }, {
122 .id = 0x0f,
123 .name = "avpcarm7r",
124 .swgroup = TEGRA_SWGROUP_AVPC,
125 .smmu = {
126 .reg = 0x228,
127 .bit = 15,
128 },
129 .la = {
130 .reg = 0x2e4,
131 .shift = 0,
132 .mask = 0xff,
133 .def = 0x04,
134 },
135 }, {
136 .id = 0x10,
137 .name = "displayhc",
138 .swgroup = TEGRA_SWGROUP_DC,
139 .smmu = {
140 .reg = 0x228,
141 .bit = 16,
142 },
143 .la = {
144 .reg = 0x2f0,
145 .shift = 0,
146 .mask = 0xff,
147 .def = 0x50,
148 },
149 }, {
150 .id = 0x11,
151 .name = "displayhcb",
152 .swgroup = TEGRA_SWGROUP_DCB,
153 .smmu = {
154 .reg = 0x228,
155 .bit = 17,
156 },
157 .la = {
158 .reg = 0x2fc,
159 .shift = 0,
160 .mask = 0xff,
161 .def = 0x50,
162 },
163 }, {
164 .id = 0x15,
165 .name = "hdar",
166 .swgroup = TEGRA_SWGROUP_HDA,
167 .smmu = {
168 .reg = 0x228,
169 .bit = 21,
170 },
171 .la = {
172 .reg = 0x318,
173 .shift = 0,
174 .mask = 0xff,
175 .def = 0x24,
176 },
177 }, {
178 .id = 0x16,
179 .name = "host1xdmar",
180 .swgroup = TEGRA_SWGROUP_HC,
181 .smmu = {
182 .reg = 0x228,
183 .bit = 22,
184 },
185 .la = {
186 .reg = 0x310,
187 .shift = 0,
188 .mask = 0xff,
189 .def = 0x1e,
190 },
191 }, {
192 .id = 0x17,
193 .name = "host1xr",
194 .swgroup = TEGRA_SWGROUP_HC,
195 .smmu = {
196 .reg = 0x228,
197 .bit = 23,
198 },
199 .la = {
200 .reg = 0x310,
201 .shift = 16,
202 .mask = 0xff,
203 .def = 0x50,
204 },
205 }, {
206 .id = 0x1c,
207 .name = "msencsrd",
208 .swgroup = TEGRA_SWGROUP_MSENC,
209 .smmu = {
210 .reg = 0x228,
211 .bit = 28,
212 },
213 .la = {
214 .reg = 0x328,
215 .shift = 0,
216 .mask = 0xff,
217 .def = 0x23,
218 },
219 }, {
220 .id = 0x1d,
221 .name = "ppcsahbdmar",
222 .swgroup = TEGRA_SWGROUP_PPCS,
223 .smmu = {
224 .reg = 0x228,
225 .bit = 29,
226 },
227 .la = {
228 .reg = 0x344,
229 .shift = 0,
230 .mask = 0xff,
231 .def = 0x49,
232 },
233 }, {
234 .id = 0x1e,
235 .name = "ppcsahbslvr",
236 .swgroup = TEGRA_SWGROUP_PPCS,
237 .smmu = {
238 .reg = 0x228,
239 .bit = 30,
240 },
241 .la = {
242 .reg = 0x344,
243 .shift = 16,
244 .mask = 0xff,
245 .def = 0x1a,
246 },
247 }, {
248 .id = 0x1f,
249 .name = "satar",
250 .swgroup = TEGRA_SWGROUP_SATA,
251 .smmu = {
252 .reg = 0x228,
253 .bit = 31,
254 },
255 .la = {
256 .reg = 0x350,
257 .shift = 0,
258 .mask = 0xff,
259 .def = 0x65,
260 },
261 }, {
262 .id = 0x22,
263 .name = "vdebsevr",
264 .swgroup = TEGRA_SWGROUP_VDE,
265 .smmu = {
266 .reg = 0x22c,
267 .bit = 2,
268 },
269 .la = {
270 .reg = 0x354,
271 .shift = 0,
272 .mask = 0xff,
273 .def = 0x4f,
274 },
275 }, {
276 .id = 0x23,
277 .name = "vdember",
278 .swgroup = TEGRA_SWGROUP_VDE,
279 .smmu = {
280 .reg = 0x22c,
281 .bit = 3,
282 },
283 .la = {
284 .reg = 0x354,
285 .shift = 16,
286 .mask = 0xff,
287 .def = 0x3d,
288 },
289 }, {
290 .id = 0x24,
291 .name = "vdemcer",
292 .swgroup = TEGRA_SWGROUP_VDE,
293 .smmu = {
294 .reg = 0x22c,
295 .bit = 4,
296 },
297 .la = {
298 .reg = 0x358,
299 .shift = 0,
300 .mask = 0xff,
301 .def = 0x66,
302 },
303 }, {
304 .id = 0x25,
305 .name = "vdetper",
306 .swgroup = TEGRA_SWGROUP_VDE,
307 .smmu = {
308 .reg = 0x22c,
309 .bit = 5,
310 },
311 .la = {
312 .reg = 0x358,
313 .shift = 16,
314 .mask = 0xff,
315 .def = 0xa5,
316 },
317 }, {
318 .id = 0x26,
319 .name = "mpcorelpr",
320 .swgroup = TEGRA_SWGROUP_MPCORELP,
321 .la = {
322 .reg = 0x324,
323 .shift = 0,
324 .mask = 0xff,
325 .def = 0x04,
326 },
327 }, {
328 .id = 0x27,
329 .name = "mpcorer",
330 .swgroup = TEGRA_SWGROUP_MPCORE,
331 .la = {
332 .reg = 0x320,
333 .shift = 0,
334 .mask = 0xff,
335 .def = 0x04,
336 },
337 }, {
338 .id = 0x2b,
339 .name = "msencswr",
340 .swgroup = TEGRA_SWGROUP_MSENC,
341 .smmu = {
342 .reg = 0x22c,
343 .bit = 11,
344 },
345 .la = {
346 .reg = 0x328,
347 .shift = 16,
348 .mask = 0xff,
349 .def = 0x80,
350 },
351 }, {
352 .id = 0x31,
353 .name = "afiw",
354 .swgroup = TEGRA_SWGROUP_AFI,
355 .smmu = {
356 .reg = 0x22c,
357 .bit = 17,
358 },
359 .la = {
360 .reg = 0x2e0,
361 .shift = 16,
362 .mask = 0xff,
363 .def = 0x80,
364 },
365 }, {
366 .id = 0x32,
367 .name = "avpcarm7w",
368 .swgroup = TEGRA_SWGROUP_AVPC,
369 .smmu = {
370 .reg = 0x22c,
371 .bit = 18,
372 },
373 .la = {
374 .reg = 0x2e4,
375 .shift = 16,
376 .mask = 0xff,
377 .def = 0x80,
378 },
379 }, {
380 .id = 0x35,
381 .name = "hdaw",
382 .swgroup = TEGRA_SWGROUP_HDA,
383 .smmu = {
384 .reg = 0x22c,
385 .bit = 21,
386 },
387 .la = {
388 .reg = 0x318,
389 .shift = 16,
390 .mask = 0xff,
391 .def = 0x80,
392 },
393 }, {
394 .id = 0x36,
395 .name = "host1xw",
396 .swgroup = TEGRA_SWGROUP_HC,
397 .smmu = {
398 .reg = 0x22c,
399 .bit = 22,
400 },
401 .la = {
402 .reg = 0x314,
403 .shift = 0,
404 .mask = 0xff,
405 .def = 0x80,
406 },
407 }, {
408 .id = 0x38,
409 .name = "mpcorelpw",
410 .swgroup = TEGRA_SWGROUP_MPCORELP,
411 .la = {
412 .reg = 0x324,
413 .shift = 16,
414 .mask = 0xff,
415 .def = 0x80,
416 },
417 }, {
418 .id = 0x39,
419 .name = "mpcorew",
420 .swgroup = TEGRA_SWGROUP_MPCORE,
421 .la = {
422 .reg = 0x320,
423 .shift = 16,
424 .mask = 0xff,
425 .def = 0x80,
426 },
427 }, {
428 .id = 0x3b,
429 .name = "ppcsahbdmaw",
430 .swgroup = TEGRA_SWGROUP_PPCS,
431 .smmu = {
432 .reg = 0x22c,
433 .bit = 27,
434 },
435 .la = {
436 .reg = 0x348,
437 .shift = 0,
438 .mask = 0xff,
439 .def = 0x80,
440 },
441 }, {
442 .id = 0x3c,
443 .name = "ppcsahbslvw",
444 .swgroup = TEGRA_SWGROUP_PPCS,
445 .smmu = {
446 .reg = 0x22c,
447 .bit = 28,
448 },
449 .la = {
450 .reg = 0x348,
451 .shift = 16,
452 .mask = 0xff,
453 .def = 0x80,
454 },
455 }, {
456 .id = 0x3d,
457 .name = "sataw",
458 .swgroup = TEGRA_SWGROUP_SATA,
459 .smmu = {
460 .reg = 0x22c,
461 .bit = 29,
462 },
463 .la = {
464 .reg = 0x350,
465 .shift = 16,
466 .mask = 0xff,
467 .def = 0x65,
468 },
469 }, {
470 .id = 0x3e,
471 .name = "vdebsevw",
472 .swgroup = TEGRA_SWGROUP_VDE,
473 .smmu = {
474 .reg = 0x22c,
475 .bit = 30,
476 },
477 .la = {
478 .reg = 0x35c,
479 .shift = 0,
480 .mask = 0xff,
481 .def = 0x80,
482 },
483 }, {
484 .id = 0x3f,
485 .name = "vdedbgw",
486 .swgroup = TEGRA_SWGROUP_VDE,
487 .smmu = {
488 .reg = 0x22c,
489 .bit = 31,
490 },
491 .la = {
492 .reg = 0x35c,
493 .shift = 16,
494 .mask = 0xff,
495 .def = 0x80,
496 },
497 }, {
498 .id = 0x40,
499 .name = "vdembew",
500 .swgroup = TEGRA_SWGROUP_VDE,
501 .smmu = {
502 .reg = 0x230,
503 .bit = 0,
504 },
505 .la = {
506 .reg = 0x360,
507 .shift = 0,
508 .mask = 0xff,
509 .def = 0x80,
510 },
511 }, {
512 .id = 0x41,
513 .name = "vdetpmw",
514 .swgroup = TEGRA_SWGROUP_VDE,
515 .smmu = {
516 .reg = 0x230,
517 .bit = 1,
518 },
519 .la = {
520 .reg = 0x360,
521 .shift = 16,
522 .mask = 0xff,
523 .def = 0x80,
524 },
525 }, {
526 .id = 0x44,
527 .name = "ispra",
528 .swgroup = TEGRA_SWGROUP_ISP2,
529 .smmu = {
530 .reg = 0x230,
531 .bit = 4,
532 },
533 .la = {
534 .reg = 0x370,
535 .shift = 0,
536 .mask = 0xff,
537 .def = 0x18,
538 },
539 }, {
540 .id = 0x46,
541 .name = "ispwa",
542 .swgroup = TEGRA_SWGROUP_ISP2,
543 .smmu = {
544 .reg = 0x230,
545 .bit = 6,
546 },
547 .la = {
548 .reg = 0x374,
549 .shift = 0,
550 .mask = 0xff,
551 .def = 0x80,
552 },
553 }, {
554 .id = 0x47,
555 .name = "ispwb",
556 .swgroup = TEGRA_SWGROUP_ISP2,
557 .smmu = {
558 .reg = 0x230,
559 .bit = 7,
560 },
561 .la = {
562 .reg = 0x374,
563 .shift = 16,
564 .mask = 0xff,
565 .def = 0x80,
566 },
567 }, {
568 .id = 0x4a,
569 .name = "xusb_hostr",
570 .swgroup = TEGRA_SWGROUP_XUSB_HOST,
571 .smmu = {
572 .reg = 0x230,
573 .bit = 10,
574 },
575 .la = {
576 .reg = 0x37c,
577 .shift = 0,
578 .mask = 0xff,
579 .def = 0x39,
580 },
581 }, {
582 .id = 0x4b,
583 .name = "xusb_hostw",
584 .swgroup = TEGRA_SWGROUP_XUSB_HOST,
585 .smmu = {
586 .reg = 0x230,
587 .bit = 11,
588 },
589 .la = {
590 .reg = 0x37c,
591 .shift = 16,
592 .mask = 0xff,
593 .def = 0x80,
594 },
595 }, {
596 .id = 0x4c,
597 .name = "xusb_devr",
598 .swgroup = TEGRA_SWGROUP_XUSB_DEV,
599 .smmu = {
600 .reg = 0x230,
601 .bit = 12,
602 },
603 .la = {
604 .reg = 0x380,
605 .shift = 0,
606 .mask = 0xff,
607 .def = 0x39,
608 },
609 }, {
610 .id = 0x4d,
611 .name = "xusb_devw",
612 .swgroup = TEGRA_SWGROUP_XUSB_DEV,
613 .smmu = {
614 .reg = 0x230,
615 .bit = 13,
616 },
617 .la = {
618 .reg = 0x380,
619 .shift = 16,
620 .mask = 0xff,
621 .def = 0x80,
622 },
623 }, {
624 .id = 0x4e,
625 .name = "isprab",
626 .swgroup = TEGRA_SWGROUP_ISP2B,
627 .smmu = {
628 .reg = 0x230,
629 .bit = 14,
630 },
631 .la = {
632 .reg = 0x384,
633 .shift = 0,
634 .mask = 0xff,
635 .def = 0x18,
636 },
637 }, {
638 .id = 0x50,
639 .name = "ispwab",
640 .swgroup = TEGRA_SWGROUP_ISP2B,
641 .smmu = {
642 .reg = 0x230,
643 .bit = 16,
644 },
645 .la = {
646 .reg = 0x388,
647 .shift = 0,
648 .mask = 0xff,
649 .def = 0x80,
650 },
651 }, {
652 .id = 0x51,
653 .name = "ispwbb",
654 .swgroup = TEGRA_SWGROUP_ISP2B,
655 .smmu = {
656 .reg = 0x230,
657 .bit = 17,
658 },
659 .la = {
660 .reg = 0x388,
661 .shift = 16,
662 .mask = 0xff,
663 .def = 0x80,
664 },
665 }, {
666 .id = 0x54,
667 .name = "tsecsrd",
668 .swgroup = TEGRA_SWGROUP_TSEC,
669 .smmu = {
670 .reg = 0x230,
671 .bit = 20,
672 },
673 .la = {
674 .reg = 0x390,
675 .shift = 0,
676 .mask = 0xff,
677 .def = 0x9b,
678 },
679 }, {
680 .id = 0x55,
681 .name = "tsecswr",
682 .swgroup = TEGRA_SWGROUP_TSEC,
683 .smmu = {
684 .reg = 0x230,
685 .bit = 21,
686 },
687 .la = {
688 .reg = 0x390,
689 .shift = 16,
690 .mask = 0xff,
691 .def = 0x80,
692 },
693 }, {
694 .id = 0x56,
695 .name = "a9avpscr",
696 .swgroup = TEGRA_SWGROUP_A9AVP,
697 .smmu = {
698 .reg = 0x230,
699 .bit = 22,
700 },
701 .la = {
702 .reg = 0x3a4,
703 .shift = 0,
704 .mask = 0xff,
705 .def = 0x04,
706 },
707 }, {
708 .id = 0x57,
709 .name = "a9avpscw",
710 .swgroup = TEGRA_SWGROUP_A9AVP,
711 .smmu = {
712 .reg = 0x230,
713 .bit = 23,
714 },
715 .la = {
716 .reg = 0x3a4,
717 .shift = 16,
718 .mask = 0xff,
719 .def = 0x80,
720 },
721 }, {
722 .id = 0x58,
723 .name = "gpusrd",
724 .swgroup = TEGRA_SWGROUP_GPU,
725 .smmu = {
726 /* read-only */
727 .reg = 0x230,
728 .bit = 24,
729 },
730 .la = {
731 .reg = 0x3c8,
732 .shift = 0,
733 .mask = 0xff,
734 .def = 0x1a,
735 },
736 }, {
737 .id = 0x59,
738 .name = "gpuswr",
739 .swgroup = TEGRA_SWGROUP_GPU,
740 .smmu = {
741 /* read-only */
742 .reg = 0x230,
743 .bit = 25,
744 },
745 .la = {
746 .reg = 0x3c8,
747 .shift = 16,
748 .mask = 0xff,
749 .def = 0x80,
750 },
751 }, {
752 .id = 0x5a,
753 .name = "displayt",
754 .swgroup = TEGRA_SWGROUP_DC,
755 .smmu = {
756 .reg = 0x230,
757 .bit = 26,
758 },
759 .la = {
760 .reg = 0x2f0,
761 .shift = 16,
762 .mask = 0xff,
763 .def = 0x50,
764 },
765 }, {
766 .id = 0x60,
767 .name = "sdmmcra",
768 .swgroup = TEGRA_SWGROUP_SDMMC1A,
769 .smmu = {
770 .reg = 0x234,
771 .bit = 0,
772 },
773 .la = {
774 .reg = 0x3b8,
775 .shift = 0,
776 .mask = 0xff,
777 .def = 0x49,
778 },
779 }, {
780 .id = 0x61,
781 .name = "sdmmcraa",
782 .swgroup = TEGRA_SWGROUP_SDMMC2A,
783 .smmu = {
784 .reg = 0x234,
785 .bit = 1,
786 },
787 .la = {
788 .reg = 0x3bc,
789 .shift = 0,
790 .mask = 0xff,
791 .def = 0x49,
792 },
793 }, {
794 .id = 0x62,
795 .name = "sdmmcr",
796 .swgroup = TEGRA_SWGROUP_SDMMC3A,
797 .smmu = {
798 .reg = 0x234,
799 .bit = 2,
800 },
801 .la = {
802 .reg = 0x3c0,
803 .shift = 0,
804 .mask = 0xff,
805 .def = 0x49,
806 },
807 }, {
808 .id = 0x63,
809 .swgroup = TEGRA_SWGROUP_SDMMC4A,
810 .name = "sdmmcrab",
811 .smmu = {
812 .reg = 0x234,
813 .bit = 3,
814 },
815 .la = {
816 .reg = 0x3c4,
817 .shift = 0,
818 .mask = 0xff,
819 .def = 0x49,
820 },
821 }, {
822 .id = 0x64,
823 .name = "sdmmcwa",
824 .swgroup = TEGRA_SWGROUP_SDMMC1A,
825 .smmu = {
826 .reg = 0x234,
827 .bit = 4,
828 },
829 .la = {
830 .reg = 0x3b8,
831 .shift = 16,
832 .mask = 0xff,
833 .def = 0x80,
834 },
835 }, {
836 .id = 0x65,
837 .name = "sdmmcwaa",
838 .swgroup = TEGRA_SWGROUP_SDMMC2A,
839 .smmu = {
840 .reg = 0x234,
841 .bit = 5,
842 },
843 .la = {
844 .reg = 0x3bc,
845 .shift = 16,
846 .mask = 0xff,
847 .def = 0x80,
848 },
849 }, {
850 .id = 0x66,
851 .name = "sdmmcw",
852 .swgroup = TEGRA_SWGROUP_SDMMC3A,
853 .smmu = {
854 .reg = 0x234,
855 .bit = 6,
856 },
857 .la = {
858 .reg = 0x3c0,
859 .shift = 16,
860 .mask = 0xff,
861 .def = 0x80,
862 },
863 }, {
864 .id = 0x67,
865 .name = "sdmmcwab",
866 .swgroup = TEGRA_SWGROUP_SDMMC4A,
867 .smmu = {
868 .reg = 0x234,
869 .bit = 7,
870 },
871 .la = {
872 .reg = 0x3c4,
873 .shift = 16,
874 .mask = 0xff,
875 .def = 0x80,
876 },
877 }, {
878 .id = 0x6c,
879 .name = "vicsrd",
880 .swgroup = TEGRA_SWGROUP_VIC,
881 .smmu = {
882 .reg = 0x234,
883 .bit = 12,
884 },
885 .la = {
886 .reg = 0x394,
887 .shift = 0,
888 .mask = 0xff,
889 .def = 0x1a,
890 },
891 }, {
892 .id = 0x6d,
893 .name = "vicswr",
894 .swgroup = TEGRA_SWGROUP_VIC,
895 .smmu = {
896 .reg = 0x234,
897 .bit = 13,
898 },
899 .la = {
900 .reg = 0x394,
901 .shift = 16,
902 .mask = 0xff,
903 .def = 0x80,
904 },
905 }, {
906 .id = 0x72,
907 .name = "viw",
908 .swgroup = TEGRA_SWGROUP_VI,
909 .smmu = {
910 .reg = 0x234,
911 .bit = 18,
912 },
913 .la = {
914 .reg = 0x398,
915 .shift = 0,
916 .mask = 0xff,
917 .def = 0x80,
918 },
919 }, {
920 .id = 0x73,
921 .name = "displayd",
922 .swgroup = TEGRA_SWGROUP_DC,
923 .smmu = {
924 .reg = 0x234,
925 .bit = 19,
926 },
927 .la = {
928 .reg = 0x3c8,
929 .shift = 0,
930 .mask = 0xff,
931 .def = 0x50,
932 },
933 },
934};
935
936static const struct tegra_smmu_swgroup tegra124_swgroups[] = {
937 { .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 },
938 { .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 },
939 { .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 },
940 { .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c },
941 { .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 },
942 { .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 },
943 { .swgroup = TEGRA_SWGROUP_MSENC, .reg = 0x264 },
944 { .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 },
945 { .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x274 },
946 { .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c },
947 { .swgroup = TEGRA_SWGROUP_ISP2, .reg = 0x258 },
948 { .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 },
949 { .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c },
950 { .swgroup = TEGRA_SWGROUP_ISP2B, .reg = 0xaa4 },
951 { .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 },
952 { .swgroup = TEGRA_SWGROUP_A9AVP, .reg = 0x290 },
953 { .swgroup = TEGRA_SWGROUP_GPU, .reg = 0xaac },
954 { .swgroup = TEGRA_SWGROUP_SDMMC1A, .reg = 0xa94 },
955 { .swgroup = TEGRA_SWGROUP_SDMMC2A, .reg = 0xa98 },
956 { .swgroup = TEGRA_SWGROUP_SDMMC3A, .reg = 0xa9c },
957 { .swgroup = TEGRA_SWGROUP_SDMMC4A, .reg = 0xaa0 },
958 { .swgroup = TEGRA_SWGROUP_VIC, .reg = 0x284 },
959 { .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 },
960};
961
962#ifdef CONFIG_ARCH_TEGRA_124_SOC
963static void tegra124_flush_dcache(struct page *page, unsigned long offset,
964 size_t size)
965{
966 phys_addr_t phys = page_to_phys(page) + offset;
967 void *virt = page_address(page) + offset;
968
969 __cpuc_flush_dcache_area(virt, size);
970 outer_flush_range(phys, phys + size);
971}
972
973static const struct tegra_smmu_ops tegra124_smmu_ops = {
974 .flush_dcache = tegra124_flush_dcache,
975};
976
977static const struct tegra_smmu_soc tegra124_smmu_soc = {
978 .clients = tegra124_mc_clients,
979 .num_clients = ARRAY_SIZE(tegra124_mc_clients),
980 .swgroups = tegra124_swgroups,
981 .num_swgroups = ARRAY_SIZE(tegra124_swgroups),
982 .supports_round_robin_arbitration = true,
983 .supports_request_limit = true,
984 .num_asids = 128,
985 .ops = &tegra124_smmu_ops,
986};
987
988const struct tegra_mc_soc tegra124_mc_soc = {
989 .clients = tegra124_mc_clients,
990 .num_clients = ARRAY_SIZE(tegra124_mc_clients),
991 .num_address_bits = 34,
992 .atom_size = 32,
993 .smmu = &tegra124_smmu_soc,
994};
995#endif /* CONFIG_ARCH_TEGRA_124_SOC */
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
new file mode 100644
index 000000000000..71fe9376fe53
--- /dev/null
+++ b/drivers/memory/tegra/tegra30.c
@@ -0,0 +1,970 @@
1/*
2 * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/of.h>
10#include <linux/mm.h>
11
12#include <asm/cacheflush.h>
13
14#include <dt-bindings/memory/tegra30-mc.h>
15
16#include "mc.h"
17
18static const struct tegra_mc_client tegra30_mc_clients[] = {
19 {
20 .id = 0x00,
21 .name = "ptcr",
22 .swgroup = TEGRA_SWGROUP_PTC,
23 }, {
24 .id = 0x01,
25 .name = "display0a",
26 .swgroup = TEGRA_SWGROUP_DC,
27 .smmu = {
28 .reg = 0x228,
29 .bit = 1,
30 },
31 .la = {
32 .reg = 0x2e8,
33 .shift = 0,
34 .mask = 0xff,
35 .def = 0x4e,
36 },
37 }, {
38 .id = 0x02,
39 .name = "display0ab",
40 .swgroup = TEGRA_SWGROUP_DCB,
41 .smmu = {
42 .reg = 0x228,
43 .bit = 2,
44 },
45 .la = {
46 .reg = 0x2f4,
47 .shift = 0,
48 .mask = 0xff,
49 .def = 0x4e,
50 },
51 }, {
52 .id = 0x03,
53 .name = "display0b",
54 .swgroup = TEGRA_SWGROUP_DC,
55 .smmu = {
56 .reg = 0x228,
57 .bit = 3,
58 },
59 .la = {
60 .reg = 0x2e8,
61 .shift = 16,
62 .mask = 0xff,
63 .def = 0x4e,
64 },
65 }, {
66 .id = 0x04,
67 .name = "display0bb",
68 .swgroup = TEGRA_SWGROUP_DCB,
69 .smmu = {
70 .reg = 0x228,
71 .bit = 4,
72 },
73 .la = {
74 .reg = 0x2f4,
75 .shift = 16,
76 .mask = 0xff,
77 .def = 0x4e,
78 },
79 }, {
80 .id = 0x05,
81 .name = "display0c",
82 .swgroup = TEGRA_SWGROUP_DC,
83 .smmu = {
84 .reg = 0x228,
85 .bit = 5,
86 },
87 .la = {
88 .reg = 0x2ec,
89 .shift = 0,
90 .mask = 0xff,
91 .def = 0x4e,
92 },
93 }, {
94 .id = 0x06,
95 .name = "display0cb",
96 .swgroup = TEGRA_SWGROUP_DCB,
97 .smmu = {
98 .reg = 0x228,
99 .bit = 6,
100 },
101 .la = {
102 .reg = 0x2f8,
103 .shift = 0,
104 .mask = 0xff,
105 .def = 0x4e,
106 },
107 }, {
108 .id = 0x07,
109 .name = "display1b",
110 .swgroup = TEGRA_SWGROUP_DC,
111 .smmu = {
112 .reg = 0x228,
113 .bit = 7,
114 },
115 .la = {
116 .reg = 0x2ec,
117 .shift = 16,
118 .mask = 0xff,
119 .def = 0x4e,
120 },
121 }, {
122 .id = 0x08,
123 .name = "display1bb",
124 .swgroup = TEGRA_SWGROUP_DCB,
125 .smmu = {
126 .reg = 0x228,
127 .bit = 8,
128 },
129 .la = {
130 .reg = 0x2f8,
131 .shift = 16,
132 .mask = 0xff,
133 .def = 0x4e,
134 },
135 }, {
136 .id = 0x09,
137 .name = "eppup",
138 .swgroup = TEGRA_SWGROUP_EPP,
139 .smmu = {
140 .reg = 0x228,
141 .bit = 9,
142 },
143 .la = {
144 .reg = 0x300,
145 .shift = 0,
146 .mask = 0xff,
147 .def = 0x17,
148 },
149 }, {
150 .id = 0x0a,
151 .name = "g2pr",
152 .swgroup = TEGRA_SWGROUP_G2,
153 .smmu = {
154 .reg = 0x228,
155 .bit = 10,
156 },
157 .la = {
158 .reg = 0x308,
159 .shift = 0,
160 .mask = 0xff,
161 .def = 0x09,
162 },
163 }, {
164 .id = 0x0b,
165 .name = "g2sr",
166 .swgroup = TEGRA_SWGROUP_G2,
167 .smmu = {
168 .reg = 0x228,
169 .bit = 11,
170 },
171 .la = {
172 .reg = 0x308,
173 .shift = 16,
174 .mask = 0xff,
175 .def = 0x09,
176 },
177 }, {
178 .id = 0x0c,
179 .name = "mpeunifbr",
180 .swgroup = TEGRA_SWGROUP_MPE,
181 .smmu = {
182 .reg = 0x228,
183 .bit = 12,
184 },
185 .la = {
186 .reg = 0x328,
187 .shift = 0,
188 .mask = 0xff,
189 .def = 0x50,
190 },
191 }, {
192 .id = 0x0d,
193 .name = "viruv",
194 .swgroup = TEGRA_SWGROUP_VI,
195 .smmu = {
196 .reg = 0x228,
197 .bit = 13,
198 },
199 .la = {
200 .reg = 0x364,
201 .shift = 0,
202 .mask = 0xff,
203 .def = 0x2c,
204 },
205 }, {
206 .id = 0x0e,
207 .name = "afir",
208 .swgroup = TEGRA_SWGROUP_AFI,
209 .smmu = {
210 .reg = 0x228,
211 .bit = 14,
212 },
213 .la = {
214 .reg = 0x2e0,
215 .shift = 0,
216 .mask = 0xff,
217 .def = 0x10,
218 },
219 }, {
220 .id = 0x0f,
221 .name = "avpcarm7r",
222 .swgroup = TEGRA_SWGROUP_AVPC,
223 .smmu = {
224 .reg = 0x228,
225 .bit = 15,
226 },
227 .la = {
228 .reg = 0x2e4,
229 .shift = 0,
230 .mask = 0xff,
231 .def = 0x04,
232 },
233 }, {
234 .id = 0x10,
235 .name = "displayhc",
236 .swgroup = TEGRA_SWGROUP_DC,
237 .smmu = {
238 .reg = 0x228,
239 .bit = 16,
240 },
241 .la = {
242 .reg = 0x2f0,
243 .shift = 0,
244 .mask = 0xff,
245 .def = 0xff,
246 },
247 }, {
248 .id = 0x11,
249 .name = "displayhcb",
250 .swgroup = TEGRA_SWGROUP_DCB,
251 .smmu = {
252 .reg = 0x228,
253 .bit = 17,
254 },
255 .la = {
256 .reg = 0x2fc,
257 .shift = 0,
258 .mask = 0xff,
259 .def = 0xff,
260 },
261 }, {
262 .id = 0x12,
263 .name = "fdcdrd",
264 .swgroup = TEGRA_SWGROUP_NV,
265 .smmu = {
266 .reg = 0x228,
267 .bit = 18,
268 },
269 .la = {
270 .reg = 0x334,
271 .shift = 0,
272 .mask = 0xff,
273 .def = 0x0a,
274 },
275 }, {
276 .id = 0x13,
277 .name = "fdcdrd2",
278 .swgroup = TEGRA_SWGROUP_NV2,
279 .smmu = {
280 .reg = 0x228,
281 .bit = 19,
282 },
283 .la = {
284 .reg = 0x33c,
285 .shift = 0,
286 .mask = 0xff,
287 .def = 0x0a,
288 },
289 }, {
290 .id = 0x14,
291 .name = "g2dr",
292 .swgroup = TEGRA_SWGROUP_G2,
293 .smmu = {
294 .reg = 0x228,
295 .bit = 20,
296 },
297 .la = {
298 .reg = 0x30c,
299 .shift = 0,
300 .mask = 0xff,
301 .def = 0x0a,
302 },
303 }, {
304 .id = 0x15,
305 .name = "hdar",
306 .swgroup = TEGRA_SWGROUP_HDA,
307 .smmu = {
308 .reg = 0x228,
309 .bit = 21,
310 },
311 .la = {
312 .reg = 0x318,
313 .shift = 0,
314 .mask = 0xff,
315 .def = 0xff,
316 },
317 }, {
318 .id = 0x16,
319 .name = "host1xdmar",
320 .swgroup = TEGRA_SWGROUP_HC,
321 .smmu = {
322 .reg = 0x228,
323 .bit = 22,
324 },
325 .la = {
326 .reg = 0x310,
327 .shift = 0,
328 .mask = 0xff,
329 .def = 0x05,
330 },
331 }, {
332 .id = 0x17,
333 .name = "host1xr",
334 .swgroup = TEGRA_SWGROUP_HC,
335 .smmu = {
336 .reg = 0x228,
337 .bit = 23,
338 },
339 .la = {
340 .reg = 0x310,
341 .shift = 16,
342 .mask = 0xff,
343 .def = 0x50,
344 },
345 }, {
346 .id = 0x18,
347 .name = "idxsrd",
348 .swgroup = TEGRA_SWGROUP_NV,
349 .smmu = {
350 .reg = 0x228,
351 .bit = 24,
352 },
353 .la = {
354 .reg = 0x334,
355 .shift = 16,
356 .mask = 0xff,
357 .def = 0x13,
358 },
359 }, {
360 .id = 0x19,
361 .name = "idxsrd2",
362 .swgroup = TEGRA_SWGROUP_NV2,
363 .smmu = {
364 .reg = 0x228,
365 .bit = 25,
366 },
367 .la = {
368 .reg = 0x33c,
369 .shift = 16,
370 .mask = 0xff,
371 .def = 0x13,
372 },
373 }, {
374 .id = 0x1a,
375 .name = "mpe_ipred",
376 .swgroup = TEGRA_SWGROUP_MPE,
377 .smmu = {
378 .reg = 0x228,
379 .bit = 26,
380 },
381 .la = {
382 .reg = 0x328,
383 .shift = 16,
384 .mask = 0xff,
385 .def = 0x80,
386 },
387 }, {
388 .id = 0x1b,
389 .name = "mpeamemrd",
390 .swgroup = TEGRA_SWGROUP_MPE,
391 .smmu = {
392 .reg = 0x228,
393 .bit = 27,
394 },
395 .la = {
396 .reg = 0x32c,
397 .shift = 0,
398 .mask = 0xff,
399 .def = 0x42,
400 },
401 }, {
402 .id = 0x1c,
403 .name = "mpecsrd",
404 .swgroup = TEGRA_SWGROUP_MPE,
405 .smmu = {
406 .reg = 0x228,
407 .bit = 28,
408 },
409 .la = {
410 .reg = 0x32c,
411 .shift = 16,
412 .mask = 0xff,
413 .def = 0xff,
414 },
415 }, {
416 .id = 0x1d,
417 .name = "ppcsahbdmar",
418 .swgroup = TEGRA_SWGROUP_PPCS,
419 .smmu = {
420 .reg = 0x228,
421 .bit = 29,
422 },
423 .la = {
424 .reg = 0x344,
425 .shift = 0,
426 .mask = 0xff,
427 .def = 0x10,
428 },
429 }, {
430 .id = 0x1e,
431 .name = "ppcsahbslvr",
432 .swgroup = TEGRA_SWGROUP_PPCS,
433 .smmu = {
434 .reg = 0x228,
435 .bit = 30,
436 },
437 .la = {
438 .reg = 0x344,
439 .shift = 16,
440 .mask = 0xff,
441 .def = 0x12,
442 },
443 }, {
444 .id = 0x1f,
445 .name = "satar",
446 .swgroup = TEGRA_SWGROUP_SATA,
447 .smmu = {
448 .reg = 0x228,
449 .bit = 31,
450 },
451 .la = {
452 .reg = 0x350,
453 .shift = 0,
454 .mask = 0xff,
455 .def = 0x33,
456 },
457 }, {
458 .id = 0x20,
459 .name = "texsrd",
460 .swgroup = TEGRA_SWGROUP_NV,
461 .smmu = {
462 .reg = 0x22c,
463 .bit = 0,
464 },
465 .la = {
466 .reg = 0x338,
467 .shift = 0,
468 .mask = 0xff,
469 .def = 0x13,
470 },
471 }, {
472 .id = 0x21,
473 .name = "texsrd2",
474 .swgroup = TEGRA_SWGROUP_NV2,
475 .smmu = {
476 .reg = 0x22c,
477 .bit = 1,
478 },
479 .la = {
480 .reg = 0x340,
481 .shift = 0,
482 .mask = 0xff,
483 .def = 0x13,
484 },
485 }, {
486 .id = 0x22,
487 .name = "vdebsevr",
488 .swgroup = TEGRA_SWGROUP_VDE,
489 .smmu = {
490 .reg = 0x22c,
491 .bit = 2,
492 },
493 .la = {
494 .reg = 0x354,
495 .shift = 0,
496 .mask = 0xff,
497 .def = 0xff,
498 },
499 }, {
500 .id = 0x23,
501 .name = "vdember",
502 .swgroup = TEGRA_SWGROUP_VDE,
503 .smmu = {
504 .reg = 0x22c,
505 .bit = 3,
506 },
507 .la = {
508 .reg = 0x354,
509 .shift = 16,
510 .mask = 0xff,
511 .def = 0xd0,
512 },
513 }, {
514 .id = 0x24,
515 .name = "vdemcer",
516 .swgroup = TEGRA_SWGROUP_VDE,
517 .smmu = {
518 .reg = 0x22c,
519 .bit = 4,
520 },
521 .la = {
522 .reg = 0x358,
523 .shift = 0,
524 .mask = 0xff,
525 .def = 0x2a,
526 },
527 }, {
528 .id = 0x25,
529 .name = "vdetper",
530 .swgroup = TEGRA_SWGROUP_VDE,
531 .smmu = {
532 .reg = 0x22c,
533 .bit = 5,
534 },
535 .la = {
536 .reg = 0x358,
537 .shift = 16,
538 .mask = 0xff,
539 .def = 0x74,
540 },
541 }, {
542 .id = 0x26,
543 .name = "mpcorelpr",
544 .swgroup = TEGRA_SWGROUP_MPCORELP,
545 .la = {
546 .reg = 0x324,
547 .shift = 0,
548 .mask = 0xff,
549 .def = 0x04,
550 },
551 }, {
552 .id = 0x27,
553 .name = "mpcorer",
554 .swgroup = TEGRA_SWGROUP_MPCORE,
555 .la = {
556 .reg = 0x320,
557 .shift = 0,
558 .mask = 0xff,
559 .def = 0x04,
560 },
561 }, {
562 .id = 0x28,
563 .name = "eppu",
564 .swgroup = TEGRA_SWGROUP_EPP,
565 .smmu = {
566 .reg = 0x22c,
567 .bit = 8,
568 },
569 .la = {
570 .reg = 0x300,
571 .shift = 16,
572 .mask = 0xff,
573 .def = 0x6c,
574 },
575 }, {
576 .id = 0x29,
577 .name = "eppv",
578 .swgroup = TEGRA_SWGROUP_EPP,
579 .smmu = {
580 .reg = 0x22c,
581 .bit = 9,
582 },
583 .la = {
584 .reg = 0x304,
585 .shift = 0,
586 .mask = 0xff,
587 .def = 0x6c,
588 },
589 }, {
590 .id = 0x2a,
591 .name = "eppy",
592 .swgroup = TEGRA_SWGROUP_EPP,
593 .smmu = {
594 .reg = 0x22c,
595 .bit = 10,
596 },
597 .la = {
598 .reg = 0x304,
599 .shift = 16,
600 .mask = 0xff,
601 .def = 0x6c,
602 },
603 }, {
604 .id = 0x2b,
605 .name = "mpeunifbw",
606 .swgroup = TEGRA_SWGROUP_MPE,
607 .smmu = {
608 .reg = 0x22c,
609 .bit = 11,
610 },
611 .la = {
612 .reg = 0x330,
613 .shift = 0,
614 .mask = 0xff,
615 .def = 0x13,
616 },
617 }, {
618 .id = 0x2c,
619 .name = "viwsb",
620 .swgroup = TEGRA_SWGROUP_VI,
621 .smmu = {
622 .reg = 0x22c,
623 .bit = 12,
624 },
625 .la = {
626 .reg = 0x364,
627 .shift = 16,
628 .mask = 0xff,
629 .def = 0x12,
630 },
631 }, {
632 .id = 0x2d,
633 .name = "viwu",
634 .swgroup = TEGRA_SWGROUP_VI,
635 .smmu = {
636 .reg = 0x22c,
637 .bit = 13,
638 },
639 .la = {
640 .reg = 0x368,
641 .shift = 0,
642 .mask = 0xff,
643 .def = 0xb2,
644 },
645 }, {
646 .id = 0x2e,
647 .name = "viwv",
648 .swgroup = TEGRA_SWGROUP_VI,
649 .smmu = {
650 .reg = 0x22c,
651 .bit = 14,
652 },
653 .la = {
654 .reg = 0x368,
655 .shift = 16,
656 .mask = 0xff,
657 .def = 0xb2,
658 },
659 }, {
660 .id = 0x2f,
661 .name = "viwy",
662 .swgroup = TEGRA_SWGROUP_VI,
663 .smmu = {
664 .reg = 0x22c,
665 .bit = 15,
666 },
667 .la = {
668 .reg = 0x36c,
669 .shift = 0,
670 .mask = 0xff,
671 .def = 0x12,
672 },
673 }, {
674 .id = 0x30,
675 .name = "g2dw",
676 .swgroup = TEGRA_SWGROUP_G2,
677 .smmu = {
678 .reg = 0x22c,
679 .bit = 16,
680 },
681 .la = {
682 .reg = 0x30c,
683 .shift = 16,
684 .mask = 0xff,
685 .def = 0x9,
686 },
687 }, {
688 .id = 0x31,
689 .name = "afiw",
690 .swgroup = TEGRA_SWGROUP_AFI,
691 .smmu = {
692 .reg = 0x22c,
693 .bit = 17,
694 },
695 .la = {
696 .reg = 0x2e0,
697 .shift = 16,
698 .mask = 0xff,
699 .def = 0x0c,
700 },
701 }, {
702 .id = 0x32,
703 .name = "avpcarm7w",
704 .swgroup = TEGRA_SWGROUP_AVPC,
705 .smmu = {
706 .reg = 0x22c,
707 .bit = 18,
708 },
709 .la = {
710 .reg = 0x2e4,
711 .shift = 16,
712 .mask = 0xff,
713 .def = 0x0e,
714 },
715 }, {
716 .id = 0x33,
717 .name = "fdcdwr",
718 .swgroup = TEGRA_SWGROUP_NV,
719 .smmu = {
720 .reg = 0x22c,
721 .bit = 19,
722 },
723 .la = {
724 .reg = 0x338,
725 .shift = 16,
726 .mask = 0xff,
727 .def = 0x0a,
728 },
729 }, {
730 .id = 0x34,
731 .name = "fdcwr2",
732 .swgroup = TEGRA_SWGROUP_NV2,
733 .smmu = {
734 .reg = 0x22c,
735 .bit = 20,
736 },
737 .la = {
738 .reg = 0x340,
739 .shift = 16,
740 .mask = 0xff,
741 .def = 0x0a,
742 },
743 }, {
744 .id = 0x35,
745 .name = "hdaw",
746 .swgroup = TEGRA_SWGROUP_HDA,
747 .smmu = {
748 .reg = 0x22c,
749 .bit = 21,
750 },
751 .la = {
752 .reg = 0x318,
753 .shift = 16,
754 .mask = 0xff,
755 .def = 0xff,
756 },
757 }, {
758 .id = 0x36,
759 .name = "host1xw",
760 .swgroup = TEGRA_SWGROUP_HC,
761 .smmu = {
762 .reg = 0x22c,
763 .bit = 22,
764 },
765 .la = {
766 .reg = 0x314,
767 .shift = 0,
768 .mask = 0xff,
769 .def = 0x10,
770 },
771 }, {
772 .id = 0x37,
773 .name = "ispw",
774 .swgroup = TEGRA_SWGROUP_ISP,
775 .smmu = {
776 .reg = 0x22c,
777 .bit = 23,
778 },
779 .la = {
780 .reg = 0x31c,
781 .shift = 0,
782 .mask = 0xff,
783 .def = 0xff,
784 },
785 }, {
786 .id = 0x38,
787 .name = "mpcorelpw",
788 .swgroup = TEGRA_SWGROUP_MPCORELP,
789 .la = {
790 .reg = 0x324,
791 .shift = 16,
792 .mask = 0xff,
793 .def = 0x0e,
794 },
795 }, {
796 .id = 0x39,
797 .name = "mpcorew",
798 .swgroup = TEGRA_SWGROUP_MPCORE,
799 .la = {
800 .reg = 0x320,
801 .shift = 16,
802 .mask = 0xff,
803 .def = 0x0e,
804 },
805 }, {
806 .id = 0x3a,
807 .name = "mpecswr",
808 .swgroup = TEGRA_SWGROUP_MPE,
809 .smmu = {
810 .reg = 0x22c,
811 .bit = 26,
812 },
813 .la = {
814 .reg = 0x330,
815 .shift = 16,
816 .mask = 0xff,
817 .def = 0xff,
818 },
819 }, {
820 .id = 0x3b,
821 .name = "ppcsahbdmaw",
822 .swgroup = TEGRA_SWGROUP_PPCS,
823 .smmu = {
824 .reg = 0x22c,
825 .bit = 27,
826 },
827 .la = {
828 .reg = 0x348,
829 .shift = 0,
830 .mask = 0xff,
831 .def = 0x10,
832 },
833 }, {
834 .id = 0x3c,
835 .name = "ppcsahbslvw",
836 .swgroup = TEGRA_SWGROUP_PPCS,
837 .smmu = {
838 .reg = 0x22c,
839 .bit = 28,
840 },
841 .la = {
842 .reg = 0x348,
843 .shift = 16,
844 .mask = 0xff,
845 .def = 0x06,
846 },
847 }, {
848 .id = 0x3d,
849 .name = "sataw",
850 .swgroup = TEGRA_SWGROUP_SATA,
851 .smmu = {
852 .reg = 0x22c,
853 .bit = 29,
854 },
855 .la = {
856 .reg = 0x350,
857 .shift = 16,
858 .mask = 0xff,
859 .def = 0x33,
860 },
861 }, {
862 .id = 0x3e,
863 .name = "vdebsevw",
864 .swgroup = TEGRA_SWGROUP_VDE,
865 .smmu = {
866 .reg = 0x22c,
867 .bit = 30,
868 },
869 .la = {
870 .reg = 0x35c,
871 .shift = 0,
872 .mask = 0xff,
873 .def = 0xff,
874 },
875 }, {
876 .id = 0x3f,
877 .name = "vdedbgw",
878 .swgroup = TEGRA_SWGROUP_VDE,
879 .smmu = {
880 .reg = 0x22c,
881 .bit = 31,
882 },
883 .la = {
884 .reg = 0x35c,
885 .shift = 16,
886 .mask = 0xff,
887 .def = 0xff,
888 },
889 }, {
890 .id = 0x40,
891 .name = "vdembew",
892 .swgroup = TEGRA_SWGROUP_VDE,
893 .smmu = {
894 .reg = 0x230,
895 .bit = 0,
896 },
897 .la = {
898 .reg = 0x360,
899 .shift = 0,
900 .mask = 0xff,
901 .def = 0x42,
902 },
903 }, {
904 .id = 0x41,
905 .name = "vdetpmw",
906 .swgroup = TEGRA_SWGROUP_VDE,
907 .smmu = {
908 .reg = 0x230,
909 .bit = 1,
910 },
911 .la = {
912 .reg = 0x360,
913 .shift = 16,
914 .mask = 0xff,
915 .def = 0x2a,
916 },
917 },
918};
919
920static const struct tegra_smmu_swgroup tegra30_swgroups[] = {
921 { .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 },
922 { .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 },
923 { .swgroup = TEGRA_SWGROUP_EPP, .reg = 0x248 },
924 { .swgroup = TEGRA_SWGROUP_G2, .reg = 0x24c },
925 { .swgroup = TEGRA_SWGROUP_MPE, .reg = 0x264 },
926 { .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 },
927 { .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 },
928 { .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c },
929 { .swgroup = TEGRA_SWGROUP_NV, .reg = 0x268 },
930 { .swgroup = TEGRA_SWGROUP_NV2, .reg = 0x26c },
931 { .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 },
932 { .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 },
933 { .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 },
934 { .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x278 },
935 { .swgroup = TEGRA_SWGROUP_VDE, .reg = 0x27c },
936 { .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 },
937};
938
939static void tegra30_flush_dcache(struct page *page, unsigned long offset,
940 size_t size)
941{
942 phys_addr_t phys = page_to_phys(page) + offset;
943 void *virt = page_address(page) + offset;
944
945 __cpuc_flush_dcache_area(virt, size);
946 outer_flush_range(phys, phys + size);
947}
948
949static const struct tegra_smmu_ops tegra30_smmu_ops = {
950 .flush_dcache = tegra30_flush_dcache,
951};
952
953static const struct tegra_smmu_soc tegra30_smmu_soc = {
954 .clients = tegra30_mc_clients,
955 .num_clients = ARRAY_SIZE(tegra30_mc_clients),
956 .swgroups = tegra30_swgroups,
957 .num_swgroups = ARRAY_SIZE(tegra30_swgroups),
958 .supports_round_robin_arbitration = false,
959 .supports_request_limit = false,
960 .num_asids = 4,
961 .ops = &tegra30_smmu_ops,
962};
963
964const struct tegra_mc_soc tegra30_mc_soc = {
965 .clients = tegra30_mc_clients,
966 .num_clients = ARRAY_SIZE(tegra30_mc_clients),
967 .num_address_bits = 32,
968 .atom_size = 16,
969 .smmu = &tegra30_smmu_soc,
970};