aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memory
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
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')
-rw-r--r--drivers/memory/Kconfig12
-rw-r--r--drivers/memory/Makefile3
-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
-rw-r--r--drivers/memory/tegra30-mc.c378
10 files changed, 3272 insertions, 389 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 6d91c27fd4c8..08bd4cfca2a4 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -61,16 +61,6 @@ config TEGRA20_MC
61 analysis, especially for IOMMU/GART(Graphics Address 61 analysis, especially for IOMMU/GART(Graphics Address
62 Relocation Table) module. 62 Relocation Table) module.
63 63
64config TEGRA30_MC
65 bool "Tegra30 Memory Controller(MC) driver"
66 default y
67 depends on ARCH_TEGRA_3x_SOC
68 help
69 This driver is for the Memory Controller(MC) module available
70 in Tegra30 SoCs, mainly for a address translation fault
71 analysis, especially for IOMMU/SMMU(System Memory Management
72 Unit) module.
73
74config FSL_CORENET_CF 64config FSL_CORENET_CF
75 tristate "Freescale CoreNet Error Reporting" 65 tristate "Freescale CoreNet Error Reporting"
76 depends on FSL_SOC_BOOKE 66 depends on FSL_SOC_BOOKE
@@ -85,4 +75,6 @@ config FSL_IFC
85 bool 75 bool
86 depends on FSL_SOC 76 depends on FSL_SOC
87 77
78source "drivers/memory/tegra/Kconfig"
79
88endif 80endif
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index c32d31981be3..ad98bb232623 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -12,4 +12,5 @@ obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o
12obj-$(CONFIG_FSL_IFC) += fsl_ifc.o 12obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
13obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o 13obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
14obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o 14obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
15obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o 15
16obj-$(CONFIG_TEGRA_MC) += tegra/
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};
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
deleted file mode 100644
index ef7934535fd1..000000000000
--- a/drivers/memory/tegra30-mc.c
+++ /dev/null
@@ -1,378 +0,0 @@
1/*
2 * Tegra30 Memory Controller
3 *
4 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include <linux/err.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/ratelimit.h>
24#include <linux/platform_device.h>
25#include <linux/interrupt.h>
26#include <linux/io.h>
27
28#define DRV_NAME "tegra30-mc"
29
30#define MC_INTSTATUS 0x0
31#define MC_INTMASK 0x4
32
33#define MC_INT_ERR_SHIFT 6
34#define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT)
35#define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT)
36#define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2)
37#define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3)
38#define MC_INT_INVALID_SMMU_PAGE BIT(MC_INT_ERR_SHIFT + 4)
39
40#define MC_ERR_STATUS 0x8
41#define MC_ERR_ADR 0xc
42
43#define MC_ERR_TYPE_SHIFT 28
44#define MC_ERR_TYPE_MASK (7 << MC_ERR_TYPE_SHIFT)
45#define MC_ERR_TYPE_DECERR_EMEM 2
46#define MC_ERR_TYPE_SECURITY_TRUSTZONE 3
47#define MC_ERR_TYPE_SECURITY_CARVEOUT 4
48#define MC_ERR_TYPE_INVALID_SMMU_PAGE 6
49
50#define MC_ERR_INVALID_SMMU_PAGE_SHIFT 25
51#define MC_ERR_INVALID_SMMU_PAGE_MASK (7 << MC_ERR_INVALID_SMMU_PAGE_SHIFT)
52#define MC_ERR_RW_SHIFT 16
53#define MC_ERR_RW BIT(MC_ERR_RW_SHIFT)
54#define MC_ERR_SECURITY BIT(MC_ERR_RW_SHIFT + 1)
55
56#define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */
57
58#define MC_EMEM_ARB_CFG 0x90
59#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
60#define MC_EMEM_ARB_TIMING_RCD 0x98
61#define MC_EMEM_ARB_TIMING_RP 0x9c
62#define MC_EMEM_ARB_TIMING_RC 0xa0
63#define MC_EMEM_ARB_TIMING_RAS 0xa4
64#define MC_EMEM_ARB_TIMING_FAW 0xa8
65#define MC_EMEM_ARB_TIMING_RRD 0xac
66#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
67#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
68#define MC_EMEM_ARB_TIMING_R2R 0xb8
69#define MC_EMEM_ARB_TIMING_W2W 0xbc
70#define MC_EMEM_ARB_TIMING_R2W 0xc0
71#define MC_EMEM_ARB_TIMING_W2R 0xc4
72
73#define MC_EMEM_ARB_DA_TURNS 0xd0
74#define MC_EMEM_ARB_DA_COVERS 0xd4
75#define MC_EMEM_ARB_MISC0 0xd8
76#define MC_EMEM_ARB_MISC1 0xdc
77
78#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
79#define MC_EMEM_ARB_OVERRIDE 0xe8
80
81#define MC_TIMING_CONTROL 0xfc
82
83#define MC_CLIENT_ID_MASK 0x7f
84
85#define NUM_MC_REG_BANKS 4
86
87struct tegra30_mc {
88 void __iomem *regs[NUM_MC_REG_BANKS];
89 struct device *dev;
90 u32 ctx[0];
91};
92
93static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs)
94{
95 u32 val = 0;
96
97 if (offs < 0x10)
98 val = readl(mc->regs[0] + offs);
99 else if (offs < 0x1f0)
100 val = readl(mc->regs[1] + offs - 0x3c);
101 else if (offs < 0x228)
102 val = readl(mc->regs[2] + offs - 0x200);
103 else if (offs < 0x400)
104 val = readl(mc->regs[3] + offs - 0x284);
105
106 return val;
107}
108
109static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs)
110{
111 if (offs < 0x10)
112 writel(val, mc->regs[0] + offs);
113 else if (offs < 0x1f0)
114 writel(val, mc->regs[1] + offs - 0x3c);
115 else if (offs < 0x228)
116 writel(val, mc->regs[2] + offs - 0x200);
117 else if (offs < 0x400)
118 writel(val, mc->regs[3] + offs - 0x284);
119}
120
121static const char * const tegra30_mc_client[] = {
122 "csr_ptcr",
123 "cbr_display0a",
124 "cbr_display0ab",
125 "cbr_display0b",
126 "cbr_display0bb",
127 "cbr_display0c",
128 "cbr_display0cb",
129 "cbr_display1b",
130 "cbr_display1bb",
131 "cbr_eppup",
132 "cbr_g2pr",
133 "cbr_g2sr",
134 "cbr_mpeunifbr",
135 "cbr_viruv",
136 "csr_afir",
137 "csr_avpcarm7r",
138 "csr_displayhc",
139 "csr_displayhcb",
140 "csr_fdcdrd",
141 "csr_fdcdrd2",
142 "csr_g2dr",
143 "csr_hdar",
144 "csr_host1xdmar",
145 "csr_host1xr",
146 "csr_idxsrd",
147 "csr_idxsrd2",
148 "csr_mpe_ipred",
149 "csr_mpeamemrd",
150 "csr_mpecsrd",
151 "csr_ppcsahbdmar",
152 "csr_ppcsahbslvr",
153 "csr_satar",
154 "csr_texsrd",
155 "csr_texsrd2",
156 "csr_vdebsevr",
157 "csr_vdember",
158 "csr_vdemcer",
159 "csr_vdetper",
160 "csr_mpcorelpr",
161 "csr_mpcorer",
162 "cbw_eppu",
163 "cbw_eppv",
164 "cbw_eppy",
165 "cbw_mpeunifbw",
166 "cbw_viwsb",
167 "cbw_viwu",
168 "cbw_viwv",
169 "cbw_viwy",
170 "ccw_g2dw",
171 "csw_afiw",
172 "csw_avpcarm7w",
173 "csw_fdcdwr",
174 "csw_fdcdwr2",
175 "csw_hdaw",
176 "csw_host1xw",
177 "csw_ispw",
178 "csw_mpcorelpw",
179 "csw_mpcorew",
180 "csw_mpecswr",
181 "csw_ppcsahbdmaw",
182 "csw_ppcsahbslvw",
183 "csw_sataw",
184 "csw_vdebsevw",
185 "csw_vdedbgw",
186 "csw_vdembew",
187 "csw_vdetpmw",
188};
189
190static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
191{
192 u32 err, addr;
193 const char * const mc_int_err[] = {
194 "MC_DECERR",
195 "Unknown",
196 "MC_SECURITY_ERR",
197 "MC_ARBITRATION_EMEM",
198 "MC_SMMU_ERR",
199 };
200 const char * const err_type[] = {
201 "Unknown",
202 "Unknown",
203 "DECERR_EMEM",
204 "SECURITY_TRUSTZONE",
205 "SECURITY_CARVEOUT",
206 "Unknown",
207 "INVALID_SMMU_PAGE",
208 "Unknown",
209 };
210 char attr[6];
211 int cid, perm, type, idx;
212 const char *client = "Unknown";
213
214 idx = n - MC_INT_ERR_SHIFT;
215 if ((idx < 0) || (idx >= ARRAY_SIZE(mc_int_err)) || (idx == 1)) {
216 dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n",
217 BIT(n));
218 return;
219 }
220
221 err = mc_readl(mc, MC_ERR_STATUS);
222
223 type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT;
224 perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >>
225 MC_ERR_INVALID_SMMU_PAGE_SHIFT;
226 if (type == MC_ERR_TYPE_INVALID_SMMU_PAGE)
227 sprintf(attr, "%c-%c-%c",
228 (perm & BIT(2)) ? 'R' : '-',
229 (perm & BIT(1)) ? 'W' : '-',
230 (perm & BIT(0)) ? 'S' : '-');
231 else
232 attr[0] = '\0';
233
234 cid = err & MC_CLIENT_ID_MASK;
235 if (cid < ARRAY_SIZE(tegra30_mc_client))
236 client = tegra30_mc_client[cid];
237
238 addr = mc_readl(mc, MC_ERR_ADR);
239
240 dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n",
241 mc_int_err[idx], err, addr, client,
242 (err & MC_ERR_SECURITY) ? "secure" : "non-secure",
243 (err & MC_ERR_RW) ? "write" : "read",
244 err_type[type], attr);
245}
246
247static const u32 tegra30_mc_ctx[] = {
248 MC_EMEM_ARB_CFG,
249 MC_EMEM_ARB_OUTSTANDING_REQ,
250 MC_EMEM_ARB_TIMING_RCD,
251 MC_EMEM_ARB_TIMING_RP,
252 MC_EMEM_ARB_TIMING_RC,
253 MC_EMEM_ARB_TIMING_RAS,
254 MC_EMEM_ARB_TIMING_FAW,
255 MC_EMEM_ARB_TIMING_RRD,
256 MC_EMEM_ARB_TIMING_RAP2PRE,
257 MC_EMEM_ARB_TIMING_WAP2PRE,
258 MC_EMEM_ARB_TIMING_R2R,
259 MC_EMEM_ARB_TIMING_W2W,
260 MC_EMEM_ARB_TIMING_R2W,
261 MC_EMEM_ARB_TIMING_W2R,
262 MC_EMEM_ARB_DA_TURNS,
263 MC_EMEM_ARB_DA_COVERS,
264 MC_EMEM_ARB_MISC0,
265 MC_EMEM_ARB_MISC1,
266 MC_EMEM_ARB_RING3_THROTTLE,
267 MC_EMEM_ARB_OVERRIDE,
268 MC_INTMASK,
269};
270
271#ifdef CONFIG_PM
272static int tegra30_mc_suspend(struct device *dev)
273{
274 int i;
275 struct tegra30_mc *mc = dev_get_drvdata(dev);
276
277 for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++)
278 mc->ctx[i] = mc_readl(mc, tegra30_mc_ctx[i]);
279 return 0;
280}
281
282static int tegra30_mc_resume(struct device *dev)
283{
284 int i;
285 struct tegra30_mc *mc = dev_get_drvdata(dev);
286
287 for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++)
288 mc_writel(mc, mc->ctx[i], tegra30_mc_ctx[i]);
289
290 mc_writel(mc, 1, MC_TIMING_CONTROL);
291 /* Read-back to ensure that write reached */
292 mc_readl(mc, MC_TIMING_CONTROL);
293 return 0;
294}
295#endif
296
297static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm,
298 tegra30_mc_suspend,
299 tegra30_mc_resume, NULL);
300
301static const struct of_device_id tegra30_mc_of_match[] = {
302 { .compatible = "nvidia,tegra30-mc", },
303 {},
304};
305
306static irqreturn_t tegra30_mc_isr(int irq, void *data)
307{
308 u32 stat, mask, bit;
309 struct tegra30_mc *mc = data;
310
311 stat = mc_readl(mc, MC_INTSTATUS);
312 mask = mc_readl(mc, MC_INTMASK);
313 mask &= stat;
314 if (!mask)
315 return IRQ_NONE;
316 while ((bit = ffs(mask)) != 0) {
317 tegra30_mc_decode(mc, bit - 1);
318 mask &= ~BIT(bit - 1);
319 }
320
321 mc_writel(mc, stat, MC_INTSTATUS);
322 return IRQ_HANDLED;
323}
324
325static int tegra30_mc_probe(struct platform_device *pdev)
326{
327 struct resource *irq;
328 struct tegra30_mc *mc;
329 size_t bytes;
330 int err, i;
331 u32 intmask;
332
333 bytes = sizeof(*mc) + sizeof(u32) * ARRAY_SIZE(tegra30_mc_ctx);
334 mc = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL);
335 if (!mc)
336 return -ENOMEM;
337 mc->dev = &pdev->dev;
338
339 for (i = 0; i < ARRAY_SIZE(mc->regs); i++) {
340 struct resource *res;
341
342 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
343 mc->regs[i] = devm_ioremap_resource(&pdev->dev, res);
344 if (IS_ERR(mc->regs[i]))
345 return PTR_ERR(mc->regs[i]);
346 }
347
348 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
349 if (!irq)
350 return -ENODEV;
351 err = devm_request_irq(&pdev->dev, irq->start, tegra30_mc_isr,
352 IRQF_SHARED, dev_name(&pdev->dev), mc);
353 if (err)
354 return -ENODEV;
355
356 platform_set_drvdata(pdev, mc);
357
358 intmask = MC_INT_INVALID_SMMU_PAGE |
359 MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION;
360 mc_writel(mc, intmask, MC_INTMASK);
361 return 0;
362}
363
364static struct platform_driver tegra30_mc_driver = {
365 .probe = tegra30_mc_probe,
366 .driver = {
367 .name = DRV_NAME,
368 .owner = THIS_MODULE,
369 .of_match_table = tegra30_mc_of_match,
370 .pm = &tegra30_mc_pm,
371 },
372};
373module_platform_driver(tegra30_mc_driver);
374
375MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
376MODULE_DESCRIPTION("Tegra30 MC driver");
377MODULE_LICENSE("GPL v2");
378MODULE_ALIAS("platform:" DRV_NAME);