aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2018-05-25 08:14:34 -0400
committerOlof Johansson <olof@lixom.net>2018-05-25 08:14:34 -0400
commit6874f9de65314fcea76f7654ba93017616e6c2d9 (patch)
treeee8615063594e37df5b4a6fbbe1006505f3d8270
parent67a41cc86f372c418cef9af52993b1f6475b94ad (diff)
parenta1be3cfdfb81cc55c1b2feb73aca6945f61acddb (diff)
Merge tag 'tegra-for-4.18-memory-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers
memory: tegra: Changes for v4.18-rc1 This contains some cleanup of the memory controller driver as well as unification work to share more code between Tegra20 and later SoC generations. Also included are an implementation for the hot resets functionality by the memory controller which is required to properly reset busy hardware. * tag 'tegra-for-4.18-memory-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: dt-bindings: memory: tegra: Remove Tegra114 SATA and AFI reset definitions memory: tegra: Remove Tegra114 SATA and AFI reset definitions memory: tegra: Register SMMU after MC driver became ready memory: tegra: Add Tegra210 memory controller hot resets memory: tegra: Add Tegra124 memory controller hot resets memory: tegra: Add Tegra114 memory controller hot resets memory: tegra: Add Tegra30 memory controller hot resets memory: tegra: Add Tegra20 memory controller hot resets memory: tegra: Introduce memory client hot reset memory: tegra: Squash tegra20-mc into common tegra-mc driver memory: tegra: Remove unused headers inclusions memory: tegra: Apply interrupts mask per SoC memory: tegra: Setup interrupts mask before requesting IRQ memory: tegra: Do not handle spurious interrupts dt-bindings: memory: tegra: Add hot resets definitions Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--drivers/memory/Kconfig10
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/tegra/Makefile1
-rw-r--r--drivers/memory/tegra/mc.c362
-rw-r--r--drivers/memory/tegra/mc.h22
-rw-r--r--drivers/memory/tegra/tegra114.c33
-rw-r--r--drivers/memory/tegra/tegra124.c48
-rw-r--r--drivers/memory/tegra/tegra20.c296
-rw-r--r--drivers/memory/tegra/tegra210.c53
-rw-r--r--drivers/memory/tegra/tegra30.c35
-rw-r--r--drivers/memory/tegra20-mc.c254
-rw-r--r--include/dt-bindings/memory/tegra114-mc.h17
-rw-r--r--include/dt-bindings/memory/tegra124-mc.h25
-rw-r--r--include/dt-bindings/memory/tegra20-mc.h21
-rw-r--r--include/dt-bindings/memory/tegra210-mc.h31
-rw-r--r--include/dt-bindings/memory/tegra30-mc.h19
-rw-r--r--include/soc/tegra/mc.h37
17 files changed, 956 insertions, 309 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 19a0e83f260d..8d731d6c3e54 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -104,16 +104,6 @@ config MVEBU_DEVBUS
104 Armada 370 and Armada XP. This controller allows to handle flash 104 Armada 370 and Armada XP. This controller allows to handle flash
105 devices such as NOR, NAND, SRAM, and FPGA. 105 devices such as NOR, NAND, SRAM, and FPGA.
106 106
107config TEGRA20_MC
108 bool "Tegra20 Memory Controller(MC) driver"
109 default y
110 depends on ARCH_TEGRA_2x_SOC
111 help
112 This driver is for the Memory Controller(MC) module available
113 in Tegra20 SoCs, mainly for a address translation fault
114 analysis, especially for IOMMU/GART(Graphics Address
115 Relocation Table) module.
116
117config FSL_CORENET_CF 107config FSL_CORENET_CF
118 tristate "Freescale CoreNet Error Reporting" 108 tristate "Freescale CoreNet Error Reporting"
119 depends on FSL_SOC_BOOKE 109 depends on FSL_SOC_BOOKE
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 66f55240830e..a01ab3e22f94 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o
16obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o 16obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o
17obj-$(CONFIG_FSL_IFC) += fsl_ifc.o 17obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
18obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o 18obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
19obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
20obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o 19obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o
21obj-$(CONFIG_MTK_SMI) += mtk-smi.o 20obj-$(CONFIG_MTK_SMI) += mtk-smi.o
22obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o 21obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
index ce87a9470034..94ab16ba075b 100644
--- a/drivers/memory/tegra/Makefile
+++ b/drivers/memory/tegra/Makefile
@@ -1,6 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2tegra-mc-y := mc.o 2tegra-mc-y := mc.o
3 3
4tegra-mc-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20.o
4tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o 5tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o
5tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o 6tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o
6tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o 7tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index a4803ac192bb..bb93cc53554e 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -7,6 +7,7 @@
7 */ 7 */
8 8
9#include <linux/clk.h> 9#include <linux/clk.h>
10#include <linux/delay.h>
10#include <linux/interrupt.h> 11#include <linux/interrupt.h>
11#include <linux/kernel.h> 12#include <linux/kernel.h>
12#include <linux/module.h> 13#include <linux/module.h>
@@ -20,14 +21,6 @@
20#include "mc.h" 21#include "mc.h"
21 22
22#define MC_INTSTATUS 0x000 23#define MC_INTSTATUS 0x000
23#define MC_INT_DECERR_MTS (1 << 16)
24#define MC_INT_SECERR_SEC (1 << 13)
25#define MC_INT_DECERR_VPR (1 << 12)
26#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11)
27#define MC_INT_INVALID_SMMU_PAGE (1 << 10)
28#define MC_INT_ARBITRATION_EMEM (1 << 9)
29#define MC_INT_SECURITY_VIOLATION (1 << 8)
30#define MC_INT_DECERR_EMEM (1 << 6)
31 24
32#define MC_INTMASK 0x004 25#define MC_INTMASK 0x004
33 26
@@ -45,6 +38,9 @@
45 38
46#define MC_ERR_ADR 0x0c 39#define MC_ERR_ADR 0x0c
47 40
41#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
42#define MC_SECURITY_VIOLATION_STATUS 0x74
43
48#define MC_EMEM_ARB_CFG 0x90 44#define MC_EMEM_ARB_CFG 0x90
49#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) (((x) & 0x1ff) << 0) 45#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) (((x) & 0x1ff) << 0)
50#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff 46#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
@@ -54,6 +50,9 @@
54#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0) 50#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
55 51
56static const struct of_device_id tegra_mc_of_match[] = { 52static const struct of_device_id tegra_mc_of_match[] = {
53#ifdef CONFIG_ARCH_TEGRA_2x_SOC
54 { .compatible = "nvidia,tegra20-mc", .data = &tegra20_mc_soc },
55#endif
57#ifdef CONFIG_ARCH_TEGRA_3x_SOC 56#ifdef CONFIG_ARCH_TEGRA_3x_SOC
58 { .compatible = "nvidia,tegra30-mc", .data = &tegra30_mc_soc }, 57 { .compatible = "nvidia,tegra30-mc", .data = &tegra30_mc_soc },
59#endif 58#endif
@@ -73,6 +72,207 @@ static const struct of_device_id tegra_mc_of_match[] = {
73}; 72};
74MODULE_DEVICE_TABLE(of, tegra_mc_of_match); 73MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
75 74
75static int terga_mc_block_dma_common(struct tegra_mc *mc,
76 const struct tegra_mc_reset *rst)
77{
78 unsigned long flags;
79 u32 value;
80
81 spin_lock_irqsave(&mc->lock, flags);
82
83 value = mc_readl(mc, rst->control) | BIT(rst->bit);
84 mc_writel(mc, value, rst->control);
85
86 spin_unlock_irqrestore(&mc->lock, flags);
87
88 return 0;
89}
90
91static bool terga_mc_dma_idling_common(struct tegra_mc *mc,
92 const struct tegra_mc_reset *rst)
93{
94 return (mc_readl(mc, rst->status) & BIT(rst->bit)) != 0;
95}
96
97static int terga_mc_unblock_dma_common(struct tegra_mc *mc,
98 const struct tegra_mc_reset *rst)
99{
100 unsigned long flags;
101 u32 value;
102
103 spin_lock_irqsave(&mc->lock, flags);
104
105 value = mc_readl(mc, rst->control) & ~BIT(rst->bit);
106 mc_writel(mc, value, rst->control);
107
108 spin_unlock_irqrestore(&mc->lock, flags);
109
110 return 0;
111}
112
113static int terga_mc_reset_status_common(struct tegra_mc *mc,
114 const struct tegra_mc_reset *rst)
115{
116 return (mc_readl(mc, rst->control) & BIT(rst->bit)) != 0;
117}
118
119const struct tegra_mc_reset_ops terga_mc_reset_ops_common = {
120 .block_dma = terga_mc_block_dma_common,
121 .dma_idling = terga_mc_dma_idling_common,
122 .unblock_dma = terga_mc_unblock_dma_common,
123 .reset_status = terga_mc_reset_status_common,
124};
125
126static inline struct tegra_mc *reset_to_mc(struct reset_controller_dev *rcdev)
127{
128 return container_of(rcdev, struct tegra_mc, reset);
129}
130
131static const struct tegra_mc_reset *tegra_mc_reset_find(struct tegra_mc *mc,
132 unsigned long id)
133{
134 unsigned int i;
135
136 for (i = 0; i < mc->soc->num_resets; i++)
137 if (mc->soc->resets[i].id == id)
138 return &mc->soc->resets[i];
139
140 return NULL;
141}
142
143static int tegra_mc_hotreset_assert(struct reset_controller_dev *rcdev,
144 unsigned long id)
145{
146 struct tegra_mc *mc = reset_to_mc(rcdev);
147 const struct tegra_mc_reset_ops *rst_ops;
148 const struct tegra_mc_reset *rst;
149 int retries = 500;
150 int err;
151
152 rst = tegra_mc_reset_find(mc, id);
153 if (!rst)
154 return -ENODEV;
155
156 rst_ops = mc->soc->reset_ops;
157 if (!rst_ops)
158 return -ENODEV;
159
160 if (rst_ops->block_dma) {
161 /* block clients DMA requests */
162 err = rst_ops->block_dma(mc, rst);
163 if (err) {
164 dev_err(mc->dev, "Failed to block %s DMA: %d\n",
165 rst->name, err);
166 return err;
167 }
168 }
169
170 if (rst_ops->dma_idling) {
171 /* wait for completion of the outstanding DMA requests */
172 while (!rst_ops->dma_idling(mc, rst)) {
173 if (!retries--) {
174 dev_err(mc->dev, "Failed to flush %s DMA\n",
175 rst->name);
176 return -EBUSY;
177 }
178
179 usleep_range(10, 100);
180 }
181 }
182
183 if (rst_ops->hotreset_assert) {
184 /* clear clients DMA requests sitting before arbitration */
185 err = rst_ops->hotreset_assert(mc, rst);
186 if (err) {
187 dev_err(mc->dev, "Failed to hot reset %s: %d\n",
188 rst->name, err);
189 return err;
190 }
191 }
192
193 return 0;
194}
195
196static int tegra_mc_hotreset_deassert(struct reset_controller_dev *rcdev,
197 unsigned long id)
198{
199 struct tegra_mc *mc = reset_to_mc(rcdev);
200 const struct tegra_mc_reset_ops *rst_ops;
201 const struct tegra_mc_reset *rst;
202 int err;
203
204 rst = tegra_mc_reset_find(mc, id);
205 if (!rst)
206 return -ENODEV;
207
208 rst_ops = mc->soc->reset_ops;
209 if (!rst_ops)
210 return -ENODEV;
211
212 if (rst_ops->hotreset_deassert) {
213 /* take out client from hot reset */
214 err = rst_ops->hotreset_deassert(mc, rst);
215 if (err) {
216 dev_err(mc->dev, "Failed to deassert hot reset %s: %d\n",
217 rst->name, err);
218 return err;
219 }
220 }
221
222 if (rst_ops->unblock_dma) {
223 /* allow new DMA requests to proceed to arbitration */
224 err = rst_ops->unblock_dma(mc, rst);
225 if (err) {
226 dev_err(mc->dev, "Failed to unblock %s DMA : %d\n",
227 rst->name, err);
228 return err;
229 }
230 }
231
232 return 0;
233}
234
235static int tegra_mc_hotreset_status(struct reset_controller_dev *rcdev,
236 unsigned long id)
237{
238 struct tegra_mc *mc = reset_to_mc(rcdev);
239 const struct tegra_mc_reset_ops *rst_ops;
240 const struct tegra_mc_reset *rst;
241
242 rst = tegra_mc_reset_find(mc, id);
243 if (!rst)
244 return -ENODEV;
245
246 rst_ops = mc->soc->reset_ops;
247 if (!rst_ops)
248 return -ENODEV;
249
250 return rst_ops->reset_status(mc, rst);
251}
252
253static const struct reset_control_ops tegra_mc_reset_ops = {
254 .assert = tegra_mc_hotreset_assert,
255 .deassert = tegra_mc_hotreset_deassert,
256 .status = tegra_mc_hotreset_status,
257};
258
259static int tegra_mc_reset_setup(struct tegra_mc *mc)
260{
261 int err;
262
263 mc->reset.ops = &tegra_mc_reset_ops;
264 mc->reset.owner = THIS_MODULE;
265 mc->reset.of_node = mc->dev->of_node;
266 mc->reset.of_reset_n_cells = 1;
267 mc->reset.nr_resets = mc->soc->num_resets;
268
269 err = reset_controller_register(&mc->reset);
270 if (err < 0)
271 return err;
272
273 return 0;
274}
275
76static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc) 276static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
77{ 277{
78 unsigned long long tick; 278 unsigned long long tick;
@@ -229,6 +429,7 @@ static int tegra_mc_setup_timings(struct tegra_mc *mc)
229static const char *const status_names[32] = { 429static const char *const status_names[32] = {
230 [ 1] = "External interrupt", 430 [ 1] = "External interrupt",
231 [ 6] = "EMEM address decode error", 431 [ 6] = "EMEM address decode error",
432 [ 7] = "GART page fault",
232 [ 8] = "Security violation", 433 [ 8] = "Security violation",
233 [ 9] = "EMEM arbitration error", 434 [ 9] = "EMEM arbitration error",
234 [10] = "Page fault", 435 [10] = "Page fault",
@@ -248,12 +449,13 @@ static const char *const error_names[8] = {
248static irqreturn_t tegra_mc_irq(int irq, void *data) 449static irqreturn_t tegra_mc_irq(int irq, void *data)
249{ 450{
250 struct tegra_mc *mc = data; 451 struct tegra_mc *mc = data;
251 unsigned long status, mask; 452 unsigned long status;
252 unsigned int bit; 453 unsigned int bit;
253 454
254 /* mask all interrupts to avoid flooding */ 455 /* mask all interrupts to avoid flooding */
255 status = mc_readl(mc, MC_INTSTATUS); 456 status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
256 mask = mc_readl(mc, MC_INTMASK); 457 if (!status)
458 return IRQ_NONE;
257 459
258 for_each_set_bit(bit, &status, 32) { 460 for_each_set_bit(bit, &status, 32) {
259 const char *error = status_names[bit] ?: "unknown"; 461 const char *error = status_names[bit] ?: "unknown";
@@ -341,12 +543,78 @@ static irqreturn_t tegra_mc_irq(int irq, void *data)
341 return IRQ_HANDLED; 543 return IRQ_HANDLED;
342} 544}
343 545
546static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data)
547{
548 struct tegra_mc *mc = data;
549 unsigned long status;
550 unsigned int bit;
551
552 /* mask all interrupts to avoid flooding */
553 status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
554 if (!status)
555 return IRQ_NONE;
556
557 for_each_set_bit(bit, &status, 32) {
558 const char *direction = "read", *secure = "";
559 const char *error = status_names[bit];
560 const char *client, *desc;
561 phys_addr_t addr;
562 u32 value, reg;
563 u8 id, type;
564
565 switch (BIT(bit)) {
566 case MC_INT_DECERR_EMEM:
567 reg = MC_DECERR_EMEM_OTHERS_STATUS;
568 value = mc_readl(mc, reg);
569
570 id = value & mc->soc->client_id_mask;
571 desc = error_names[2];
572
573 if (value & BIT(31))
574 direction = "write";
575 break;
576
577 case MC_INT_INVALID_GART_PAGE:
578 dev_err_ratelimited(mc->dev, "%s\n", error);
579 continue;
580
581 case MC_INT_SECURITY_VIOLATION:
582 reg = MC_SECURITY_VIOLATION_STATUS;
583 value = mc_readl(mc, reg);
584
585 id = value & mc->soc->client_id_mask;
586 type = (value & BIT(30)) ? 4 : 3;
587 desc = error_names[type];
588 secure = "secure ";
589
590 if (value & BIT(31))
591 direction = "write";
592 break;
593
594 default:
595 continue;
596 }
597
598 client = mc->soc->clients[id].name;
599 addr = mc_readl(mc, reg + sizeof(u32));
600
601 dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s)\n",
602 client, secure, direction, &addr, error,
603 desc);
604 }
605
606 /* clear interrupts */
607 mc_writel(mc, status, MC_INTSTATUS);
608
609 return IRQ_HANDLED;
610}
611
344static int tegra_mc_probe(struct platform_device *pdev) 612static int tegra_mc_probe(struct platform_device *pdev)
345{ 613{
346 const struct of_device_id *match; 614 const struct of_device_id *match;
347 struct resource *res; 615 struct resource *res;
348 struct tegra_mc *mc; 616 struct tegra_mc *mc;
349 u32 value; 617 void *isr;
350 int err; 618 int err;
351 619
352 match = of_match_node(tegra_mc_of_match, pdev->dev.of_node); 620 match = of_match_node(tegra_mc_of_match, pdev->dev.of_node);
@@ -358,6 +626,7 @@ static int tegra_mc_probe(struct platform_device *pdev)
358 return -ENOMEM; 626 return -ENOMEM;
359 627
360 platform_set_drvdata(pdev, mc); 628 platform_set_drvdata(pdev, mc);
629 spin_lock_init(&mc->lock);
361 mc->soc = match->data; 630 mc->soc = match->data;
362 mc->dev = &pdev->dev; 631 mc->dev = &pdev->dev;
363 632
@@ -369,18 +638,32 @@ static int tegra_mc_probe(struct platform_device *pdev)
369 if (IS_ERR(mc->regs)) 638 if (IS_ERR(mc->regs))
370 return PTR_ERR(mc->regs); 639 return PTR_ERR(mc->regs);
371 640
372 mc->clk = devm_clk_get(&pdev->dev, "mc"); 641#ifdef CONFIG_ARCH_TEGRA_2x_SOC
373 if (IS_ERR(mc->clk)) { 642 if (mc->soc == &tegra20_mc_soc) {
374 dev_err(&pdev->dev, "failed to get MC clock: %ld\n", 643 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
375 PTR_ERR(mc->clk)); 644 mc->regs2 = devm_ioremap_resource(&pdev->dev, res);
376 return PTR_ERR(mc->clk); 645 if (IS_ERR(mc->regs2))
377 } 646 return PTR_ERR(mc->regs2);
378 647
379 err = tegra_mc_setup_latency_allowance(mc); 648 isr = tegra20_mc_irq;
380 if (err < 0) { 649 } else
381 dev_err(&pdev->dev, "failed to setup latency allowance: %d\n", 650#endif
382 err); 651 {
383 return err; 652 mc->clk = devm_clk_get(&pdev->dev, "mc");
653 if (IS_ERR(mc->clk)) {
654 dev_err(&pdev->dev, "failed to get MC clock: %ld\n",
655 PTR_ERR(mc->clk));
656 return PTR_ERR(mc->clk);
657 }
658
659 err = tegra_mc_setup_latency_allowance(mc);
660 if (err < 0) {
661 dev_err(&pdev->dev, "failed to setup latency allowance: %d\n",
662 err);
663 return err;
664 }
665
666 isr = tegra_mc_irq;
384 } 667 }
385 668
386 err = tegra_mc_setup_timings(mc); 669 err = tegra_mc_setup_timings(mc);
@@ -389,13 +672,11 @@ static int tegra_mc_probe(struct platform_device *pdev)
389 return err; 672 return err;
390 } 673 }
391 674
392 if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) { 675 err = tegra_mc_reset_setup(mc);
393 mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc); 676 if (err < 0) {
394 if (IS_ERR(mc->smmu)) { 677 dev_err(&pdev->dev, "failed to register reset controller: %d\n",
395 dev_err(&pdev->dev, "failed to probe SMMU: %ld\n", 678 err);
396 PTR_ERR(mc->smmu)); 679 return err;
397 return PTR_ERR(mc->smmu);
398 }
399 } 680 }
400 681
401 mc->irq = platform_get_irq(pdev, 0); 682 mc->irq = platform_get_irq(pdev, 0);
@@ -404,7 +685,11 @@ static int tegra_mc_probe(struct platform_device *pdev)
404 return mc->irq; 685 return mc->irq;
405 } 686 }
406 687
407 err = devm_request_irq(&pdev->dev, mc->irq, tegra_mc_irq, IRQF_SHARED, 688 WARN(!mc->soc->client_id_mask, "Missing client ID mask for this SoC\n");
689
690 mc_writel(mc, mc->soc->intmask, MC_INTMASK);
691
692 err = devm_request_irq(&pdev->dev, mc->irq, isr, IRQF_SHARED,
408 dev_name(&pdev->dev), mc); 693 dev_name(&pdev->dev), mc);
409 if (err < 0) { 694 if (err < 0) {
410 dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq, 695 dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq,
@@ -412,13 +697,14 @@ static int tegra_mc_probe(struct platform_device *pdev)
412 return err; 697 return err;
413 } 698 }
414 699
415 WARN(!mc->soc->client_id_mask, "Missing client ID mask for this SoC\n"); 700 if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
416 701 mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
417 value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | 702 if (IS_ERR(mc->smmu)) {
418 MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | 703 dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
419 MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM; 704 PTR_ERR(mc->smmu));
420 705 return PTR_ERR(mc->smmu);
421 mc_writel(mc, value, MC_INTMASK); 706 }
707 }
422 708
423 return 0; 709 return 0;
424} 710}
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index ddb16676c3af..01065f12ebeb 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -14,17 +14,39 @@
14 14
15#include <soc/tegra/mc.h> 15#include <soc/tegra/mc.h>
16 16
17#define MC_INT_DECERR_MTS (1 << 16)
18#define MC_INT_SECERR_SEC (1 << 13)
19#define MC_INT_DECERR_VPR (1 << 12)
20#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11)
21#define MC_INT_INVALID_SMMU_PAGE (1 << 10)
22#define MC_INT_ARBITRATION_EMEM (1 << 9)
23#define MC_INT_SECURITY_VIOLATION (1 << 8)
24#define MC_INT_INVALID_GART_PAGE (1 << 7)
25#define MC_INT_DECERR_EMEM (1 << 6)
26
17static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset) 27static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset)
18{ 28{
29 if (mc->regs2 && offset >= 0x24)
30 return readl(mc->regs2 + offset - 0x3c);
31
19 return readl(mc->regs + offset); 32 return readl(mc->regs + offset);
20} 33}
21 34
22static inline void mc_writel(struct tegra_mc *mc, u32 value, 35static inline void mc_writel(struct tegra_mc *mc, u32 value,
23 unsigned long offset) 36 unsigned long offset)
24{ 37{
38 if (mc->regs2 && offset >= 0x24)
39 return writel(value, mc->regs2 + offset - 0x3c);
40
25 writel(value, mc->regs + offset); 41 writel(value, mc->regs + offset);
26} 42}
27 43
44extern const struct tegra_mc_reset_ops terga_mc_reset_ops_common;
45
46#ifdef CONFIG_ARCH_TEGRA_2x_SOC
47extern const struct tegra_mc_soc tegra20_mc_soc;
48#endif
49
28#ifdef CONFIG_ARCH_TEGRA_3x_SOC 50#ifdef CONFIG_ARCH_TEGRA_3x_SOC
29extern const struct tegra_mc_soc tegra30_mc_soc; 51extern const struct tegra_mc_soc tegra30_mc_soc;
30#endif 52#endif
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c
index b20e6e3e208e..6560a5101322 100644
--- a/drivers/memory/tegra/tegra114.c
+++ b/drivers/memory/tegra/tegra114.c
@@ -938,6 +938,34 @@ static const struct tegra_smmu_soc tegra114_smmu_soc = {
938 .num_asids = 4, 938 .num_asids = 4,
939}; 939};
940 940
941#define TEGRA114_MC_RESET(_name, _control, _status, _bit) \
942 { \
943 .name = #_name, \
944 .id = TEGRA114_MC_RESET_##_name, \
945 .control = _control, \
946 .status = _status, \
947 .bit = _bit, \
948 }
949
950static const struct tegra_mc_reset tegra114_mc_resets[] = {
951 TEGRA114_MC_RESET(AVPC, 0x200, 0x204, 1),
952 TEGRA114_MC_RESET(DC, 0x200, 0x204, 2),
953 TEGRA114_MC_RESET(DCB, 0x200, 0x204, 3),
954 TEGRA114_MC_RESET(EPP, 0x200, 0x204, 4),
955 TEGRA114_MC_RESET(2D, 0x200, 0x204, 5),
956 TEGRA114_MC_RESET(HC, 0x200, 0x204, 6),
957 TEGRA114_MC_RESET(HDA, 0x200, 0x204, 7),
958 TEGRA114_MC_RESET(ISP, 0x200, 0x204, 8),
959 TEGRA114_MC_RESET(MPCORE, 0x200, 0x204, 9),
960 TEGRA114_MC_RESET(MPCORELP, 0x200, 0x204, 10),
961 TEGRA114_MC_RESET(MPE, 0x200, 0x204, 11),
962 TEGRA114_MC_RESET(3D, 0x200, 0x204, 12),
963 TEGRA114_MC_RESET(3D2, 0x200, 0x204, 13),
964 TEGRA114_MC_RESET(PPCS, 0x200, 0x204, 14),
965 TEGRA114_MC_RESET(VDE, 0x200, 0x204, 16),
966 TEGRA114_MC_RESET(VI, 0x200, 0x204, 17),
967};
968
941const struct tegra_mc_soc tegra114_mc_soc = { 969const struct tegra_mc_soc tegra114_mc_soc = {
942 .clients = tegra114_mc_clients, 970 .clients = tegra114_mc_clients,
943 .num_clients = ARRAY_SIZE(tegra114_mc_clients), 971 .num_clients = ARRAY_SIZE(tegra114_mc_clients),
@@ -945,4 +973,9 @@ const struct tegra_mc_soc tegra114_mc_soc = {
945 .atom_size = 32, 973 .atom_size = 32,
946 .client_id_mask = 0x7f, 974 .client_id_mask = 0x7f,
947 .smmu = &tegra114_smmu_soc, 975 .smmu = &tegra114_smmu_soc,
976 .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
977 MC_INT_DECERR_EMEM,
978 .reset_ops = &terga_mc_reset_ops_common,
979 .resets = tegra114_mc_resets,
980 .num_resets = ARRAY_SIZE(tegra114_mc_resets),
948}; 981};
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
index 8b6360eabb8a..b561a1fe7f46 100644
--- a/drivers/memory/tegra/tegra124.c
+++ b/drivers/memory/tegra/tegra124.c
@@ -1012,6 +1012,42 @@ static const struct tegra_smmu_group_soc tegra124_groups[] = {
1012 }, 1012 },
1013}; 1013};
1014 1014
1015#define TEGRA124_MC_RESET(_name, _control, _status, _bit) \
1016 { \
1017 .name = #_name, \
1018 .id = TEGRA124_MC_RESET_##_name, \
1019 .control = _control, \
1020 .status = _status, \
1021 .bit = _bit, \
1022 }
1023
1024static const struct tegra_mc_reset tegra124_mc_resets[] = {
1025 TEGRA124_MC_RESET(AFI, 0x200, 0x204, 0),
1026 TEGRA124_MC_RESET(AVPC, 0x200, 0x204, 1),
1027 TEGRA124_MC_RESET(DC, 0x200, 0x204, 2),
1028 TEGRA124_MC_RESET(DCB, 0x200, 0x204, 3),
1029 TEGRA124_MC_RESET(HC, 0x200, 0x204, 6),
1030 TEGRA124_MC_RESET(HDA, 0x200, 0x204, 7),
1031 TEGRA124_MC_RESET(ISP2, 0x200, 0x204, 8),
1032 TEGRA124_MC_RESET(MPCORE, 0x200, 0x204, 9),
1033 TEGRA124_MC_RESET(MPCORELP, 0x200, 0x204, 10),
1034 TEGRA124_MC_RESET(MSENC, 0x200, 0x204, 11),
1035 TEGRA124_MC_RESET(PPCS, 0x200, 0x204, 14),
1036 TEGRA124_MC_RESET(SATA, 0x200, 0x204, 15),
1037 TEGRA124_MC_RESET(VDE, 0x200, 0x204, 16),
1038 TEGRA124_MC_RESET(VI, 0x200, 0x204, 17),
1039 TEGRA124_MC_RESET(VIC, 0x200, 0x204, 18),
1040 TEGRA124_MC_RESET(XUSB_HOST, 0x200, 0x204, 19),
1041 TEGRA124_MC_RESET(XUSB_DEV, 0x200, 0x204, 20),
1042 TEGRA124_MC_RESET(TSEC, 0x200, 0x204, 21),
1043 TEGRA124_MC_RESET(SDMMC1, 0x200, 0x204, 22),
1044 TEGRA124_MC_RESET(SDMMC2, 0x200, 0x204, 23),
1045 TEGRA124_MC_RESET(SDMMC3, 0x200, 0x204, 25),
1046 TEGRA124_MC_RESET(SDMMC4, 0x970, 0x974, 0),
1047 TEGRA124_MC_RESET(ISP2B, 0x970, 0x974, 1),
1048 TEGRA124_MC_RESET(GPU, 0x970, 0x974, 2),
1049};
1050
1015#ifdef CONFIG_ARCH_TEGRA_124_SOC 1051#ifdef CONFIG_ARCH_TEGRA_124_SOC
1016static const struct tegra_smmu_soc tegra124_smmu_soc = { 1052static const struct tegra_smmu_soc tegra124_smmu_soc = {
1017 .clients = tegra124_mc_clients, 1053 .clients = tegra124_mc_clients,
@@ -1035,6 +1071,12 @@ const struct tegra_mc_soc tegra124_mc_soc = {
1035 .smmu = &tegra124_smmu_soc, 1071 .smmu = &tegra124_smmu_soc,
1036 .emem_regs = tegra124_mc_emem_regs, 1072 .emem_regs = tegra124_mc_emem_regs,
1037 .num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs), 1073 .num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs),
1074 .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
1075 MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
1076 MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
1077 .reset_ops = &terga_mc_reset_ops_common,
1078 .resets = tegra124_mc_resets,
1079 .num_resets = ARRAY_SIZE(tegra124_mc_resets),
1038}; 1080};
1039#endif /* CONFIG_ARCH_TEGRA_124_SOC */ 1081#endif /* CONFIG_ARCH_TEGRA_124_SOC */
1040 1082
@@ -1059,5 +1101,11 @@ const struct tegra_mc_soc tegra132_mc_soc = {
1059 .atom_size = 32, 1101 .atom_size = 32,
1060 .client_id_mask = 0x7f, 1102 .client_id_mask = 0x7f,
1061 .smmu = &tegra132_smmu_soc, 1103 .smmu = &tegra132_smmu_soc,
1104 .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
1105 MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
1106 MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
1107 .reset_ops = &terga_mc_reset_ops_common,
1108 .resets = tegra124_mc_resets,
1109 .num_resets = ARRAY_SIZE(tegra124_mc_resets),
1062}; 1110};
1063#endif /* CONFIG_ARCH_TEGRA_132_SOC */ 1111#endif /* CONFIG_ARCH_TEGRA_132_SOC */
diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c
new file mode 100644
index 000000000000..7119e532471c
--- /dev/null
+++ b/drivers/memory/tegra/tegra20.c
@@ -0,0 +1,296 @@
1/*
2 * Copyright (C) 2012 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 <dt-bindings/memory/tegra20-mc.h>
10
11#include "mc.h"
12
13static const struct tegra_mc_client tegra20_mc_clients[] = {
14 {
15 .id = 0x00,
16 .name = "display0a",
17 }, {
18 .id = 0x01,
19 .name = "display0ab",
20 }, {
21 .id = 0x02,
22 .name = "display0b",
23 }, {
24 .id = 0x03,
25 .name = "display0bb",
26 }, {
27 .id = 0x04,
28 .name = "display0c",
29 }, {
30 .id = 0x05,
31 .name = "display0cb",
32 }, {
33 .id = 0x06,
34 .name = "display1b",
35 }, {
36 .id = 0x07,
37 .name = "display1bb",
38 }, {
39 .id = 0x08,
40 .name = "eppup",
41 }, {
42 .id = 0x09,
43 .name = "g2pr",
44 }, {
45 .id = 0x0a,
46 .name = "g2sr",
47 }, {
48 .id = 0x0b,
49 .name = "mpeunifbr",
50 }, {
51 .id = 0x0c,
52 .name = "viruv",
53 }, {
54 .id = 0x0d,
55 .name = "avpcarm7r",
56 }, {
57 .id = 0x0e,
58 .name = "displayhc",
59 }, {
60 .id = 0x0f,
61 .name = "displayhcb",
62 }, {
63 .id = 0x10,
64 .name = "fdcdrd",
65 }, {
66 .id = 0x11,
67 .name = "g2dr",
68 }, {
69 .id = 0x12,
70 .name = "host1xdmar",
71 }, {
72 .id = 0x13,
73 .name = "host1xr",
74 }, {
75 .id = 0x14,
76 .name = "idxsrd",
77 }, {
78 .id = 0x15,
79 .name = "mpcorer",
80 }, {
81 .id = 0x16,
82 .name = "mpe_ipred",
83 }, {
84 .id = 0x17,
85 .name = "mpeamemrd",
86 }, {
87 .id = 0x18,
88 .name = "mpecsrd",
89 }, {
90 .id = 0x19,
91 .name = "ppcsahbdmar",
92 }, {
93 .id = 0x1a,
94 .name = "ppcsahbslvr",
95 }, {
96 .id = 0x1b,
97 .name = "texsrd",
98 }, {
99 .id = 0x1c,
100 .name = "vdebsevr",
101 }, {
102 .id = 0x1d,
103 .name = "vdember",
104 }, {
105 .id = 0x1e,
106 .name = "vdemcer",
107 }, {
108 .id = 0x1f,
109 .name = "vdetper",
110 }, {
111 .id = 0x20,
112 .name = "eppu",
113 }, {
114 .id = 0x21,
115 .name = "eppv",
116 }, {
117 .id = 0x22,
118 .name = "eppy",
119 }, {
120 .id = 0x23,
121 .name = "mpeunifbw",
122 }, {
123 .id = 0x24,
124 .name = "viwsb",
125 }, {
126 .id = 0x25,
127 .name = "viwu",
128 }, {
129 .id = 0x26,
130 .name = "viwv",
131 }, {
132 .id = 0x27,
133 .name = "viwy",
134 }, {
135 .id = 0x28,
136 .name = "g2dw",
137 }, {
138 .id = 0x29,
139 .name = "avpcarm7w",
140 }, {
141 .id = 0x2a,
142 .name = "fdcdwr",
143 }, {
144 .id = 0x2b,
145 .name = "host1xw",
146 }, {
147 .id = 0x2c,
148 .name = "ispw",
149 }, {
150 .id = 0x2d,
151 .name = "mpcorew",
152 }, {
153 .id = 0x2e,
154 .name = "mpecswr",
155 }, {
156 .id = 0x2f,
157 .name = "ppcsahbdmaw",
158 }, {
159 .id = 0x30,
160 .name = "ppcsahbslvw",
161 }, {
162 .id = 0x31,
163 .name = "vdebsevw",
164 }, {
165 .id = 0x32,
166 .name = "vdembew",
167 }, {
168 .id = 0x33,
169 .name = "vdetpmw",
170 },
171};
172
173#define TEGRA20_MC_RESET(_name, _control, _status, _reset, _bit) \
174 { \
175 .name = #_name, \
176 .id = TEGRA20_MC_RESET_##_name, \
177 .control = _control, \
178 .status = _status, \
179 .reset = _reset, \
180 .bit = _bit, \
181 }
182
183static const struct tegra_mc_reset tegra20_mc_resets[] = {
184 TEGRA20_MC_RESET(AVPC, 0x100, 0x140, 0x104, 0),
185 TEGRA20_MC_RESET(DC, 0x100, 0x144, 0x104, 1),
186 TEGRA20_MC_RESET(DCB, 0x100, 0x148, 0x104, 2),
187 TEGRA20_MC_RESET(EPP, 0x100, 0x14c, 0x104, 3),
188 TEGRA20_MC_RESET(2D, 0x100, 0x150, 0x104, 4),
189 TEGRA20_MC_RESET(HC, 0x100, 0x154, 0x104, 5),
190 TEGRA20_MC_RESET(ISP, 0x100, 0x158, 0x104, 6),
191 TEGRA20_MC_RESET(MPCORE, 0x100, 0x15c, 0x104, 7),
192 TEGRA20_MC_RESET(MPEA, 0x100, 0x160, 0x104, 8),
193 TEGRA20_MC_RESET(MPEB, 0x100, 0x164, 0x104, 9),
194 TEGRA20_MC_RESET(MPEC, 0x100, 0x168, 0x104, 10),
195 TEGRA20_MC_RESET(3D, 0x100, 0x16c, 0x104, 11),
196 TEGRA20_MC_RESET(PPCS, 0x100, 0x170, 0x104, 12),
197 TEGRA20_MC_RESET(VDE, 0x100, 0x174, 0x104, 13),
198 TEGRA20_MC_RESET(VI, 0x100, 0x178, 0x104, 14),
199};
200
201static int terga20_mc_hotreset_assert(struct tegra_mc *mc,
202 const struct tegra_mc_reset *rst)
203{
204 unsigned long flags;
205 u32 value;
206
207 spin_lock_irqsave(&mc->lock, flags);
208
209 value = mc_readl(mc, rst->reset);
210 mc_writel(mc, value & ~BIT(rst->bit), rst->reset);
211
212 spin_unlock_irqrestore(&mc->lock, flags);
213
214 return 0;
215}
216
217static int terga20_mc_hotreset_deassert(struct tegra_mc *mc,
218 const struct tegra_mc_reset *rst)
219{
220 unsigned long flags;
221 u32 value;
222
223 spin_lock_irqsave(&mc->lock, flags);
224
225 value = mc_readl(mc, rst->reset);
226 mc_writel(mc, value | BIT(rst->bit), rst->reset);
227
228 spin_unlock_irqrestore(&mc->lock, flags);
229
230 return 0;
231}
232
233static int terga20_mc_block_dma(struct tegra_mc *mc,
234 const struct tegra_mc_reset *rst)
235{
236 unsigned long flags;
237 u32 value;
238
239 spin_lock_irqsave(&mc->lock, flags);
240
241 value = mc_readl(mc, rst->control) & ~BIT(rst->bit);
242 mc_writel(mc, value, rst->control);
243
244 spin_unlock_irqrestore(&mc->lock, flags);
245
246 return 0;
247}
248
249static bool terga20_mc_dma_idling(struct tegra_mc *mc,
250 const struct tegra_mc_reset *rst)
251{
252 return mc_readl(mc, rst->status) == 0;
253}
254
255static int terga20_mc_reset_status(struct tegra_mc *mc,
256 const struct tegra_mc_reset *rst)
257{
258 return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0;
259}
260
261static int terga20_mc_unblock_dma(struct tegra_mc *mc,
262 const struct tegra_mc_reset *rst)
263{
264 unsigned long flags;
265 u32 value;
266
267 spin_lock_irqsave(&mc->lock, flags);
268
269 value = mc_readl(mc, rst->control) | BIT(rst->bit);
270 mc_writel(mc, value, rst->control);
271
272 spin_unlock_irqrestore(&mc->lock, flags);
273
274 return 0;
275}
276
277const struct tegra_mc_reset_ops terga20_mc_reset_ops = {
278 .hotreset_assert = terga20_mc_hotreset_assert,
279 .hotreset_deassert = terga20_mc_hotreset_deassert,
280 .block_dma = terga20_mc_block_dma,
281 .dma_idling = terga20_mc_dma_idling,
282 .unblock_dma = terga20_mc_unblock_dma,
283 .reset_status = terga20_mc_reset_status,
284};
285
286const struct tegra_mc_soc tegra20_mc_soc = {
287 .clients = tegra20_mc_clients,
288 .num_clients = ARRAY_SIZE(tegra20_mc_clients),
289 .num_address_bits = 32,
290 .client_id_mask = 0x3f,
291 .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
292 MC_INT_DECERR_EMEM,
293 .reset_ops = &terga20_mc_reset_ops,
294 .resets = tegra20_mc_resets,
295 .num_resets = ARRAY_SIZE(tegra20_mc_resets),
296};
diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c
index d398bcd3fc57..d00a77160407 100644
--- a/drivers/memory/tegra/tegra210.c
+++ b/drivers/memory/tegra/tegra210.c
@@ -6,11 +6,6 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#include <linux/of.h>
10#include <linux/mm.h>
11
12#include <asm/cacheflush.h>
13
14#include <dt-bindings/memory/tegra210-mc.h> 9#include <dt-bindings/memory/tegra210-mc.h>
15 10
16#include "mc.h" 11#include "mc.h"
@@ -1085,6 +1080,48 @@ static const struct tegra_smmu_soc tegra210_smmu_soc = {
1085 .num_asids = 128, 1080 .num_asids = 128,
1086}; 1081};
1087 1082
1083#define TEGRA210_MC_RESET(_name, _control, _status, _bit) \
1084 { \
1085 .name = #_name, \
1086 .id = TEGRA210_MC_RESET_##_name, \
1087 .control = _control, \
1088 .status = _status, \
1089 .bit = _bit, \
1090 }
1091
1092static const struct tegra_mc_reset tegra210_mc_resets[] = {
1093 TEGRA210_MC_RESET(AFI, 0x200, 0x204, 0),
1094 TEGRA210_MC_RESET(AVPC, 0x200, 0x204, 1),
1095 TEGRA210_MC_RESET(DC, 0x200, 0x204, 2),
1096 TEGRA210_MC_RESET(DCB, 0x200, 0x204, 3),
1097 TEGRA210_MC_RESET(HC, 0x200, 0x204, 6),
1098 TEGRA210_MC_RESET(HDA, 0x200, 0x204, 7),
1099 TEGRA210_MC_RESET(ISP2, 0x200, 0x204, 8),
1100 TEGRA210_MC_RESET(MPCORE, 0x200, 0x204, 9),
1101 TEGRA210_MC_RESET(NVENC, 0x200, 0x204, 11),
1102 TEGRA210_MC_RESET(PPCS, 0x200, 0x204, 14),
1103 TEGRA210_MC_RESET(SATA, 0x200, 0x204, 15),
1104 TEGRA210_MC_RESET(VI, 0x200, 0x204, 17),
1105 TEGRA210_MC_RESET(VIC, 0x200, 0x204, 18),
1106 TEGRA210_MC_RESET(XUSB_HOST, 0x200, 0x204, 19),
1107 TEGRA210_MC_RESET(XUSB_DEV, 0x200, 0x204, 20),
1108 TEGRA210_MC_RESET(A9AVP, 0x200, 0x204, 21),
1109 TEGRA210_MC_RESET(TSEC, 0x200, 0x204, 22),
1110 TEGRA210_MC_RESET(SDMMC1, 0x200, 0x204, 29),
1111 TEGRA210_MC_RESET(SDMMC2, 0x200, 0x204, 30),
1112 TEGRA210_MC_RESET(SDMMC3, 0x200, 0x204, 31),
1113 TEGRA210_MC_RESET(SDMMC4, 0x970, 0x974, 0),
1114 TEGRA210_MC_RESET(ISP2B, 0x970, 0x974, 1),
1115 TEGRA210_MC_RESET(GPU, 0x970, 0x974, 2),
1116 TEGRA210_MC_RESET(NVDEC, 0x970, 0x974, 5),
1117 TEGRA210_MC_RESET(APE, 0x970, 0x974, 6),
1118 TEGRA210_MC_RESET(SE, 0x970, 0x974, 7),
1119 TEGRA210_MC_RESET(NVJPG, 0x970, 0x974, 8),
1120 TEGRA210_MC_RESET(AXIAP, 0x970, 0x974, 11),
1121 TEGRA210_MC_RESET(ETR, 0x970, 0x974, 12),
1122 TEGRA210_MC_RESET(TSECB, 0x970, 0x974, 13),
1123};
1124
1088const struct tegra_mc_soc tegra210_mc_soc = { 1125const struct tegra_mc_soc tegra210_mc_soc = {
1089 .clients = tegra210_mc_clients, 1126 .clients = tegra210_mc_clients,
1090 .num_clients = ARRAY_SIZE(tegra210_mc_clients), 1127 .num_clients = ARRAY_SIZE(tegra210_mc_clients),
@@ -1092,4 +1129,10 @@ const struct tegra_mc_soc tegra210_mc_soc = {
1092 .atom_size = 64, 1129 .atom_size = 64,
1093 .client_id_mask = 0xff, 1130 .client_id_mask = 0xff,
1094 .smmu = &tegra210_smmu_soc, 1131 .smmu = &tegra210_smmu_soc,
1132 .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
1133 MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
1134 MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
1135 .reset_ops = &terga_mc_reset_ops_common,
1136 .resets = tegra210_mc_resets,
1137 .num_resets = ARRAY_SIZE(tegra210_mc_resets),
1095}; 1138};
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
index d756c837f23e..bee5314ed404 100644
--- a/drivers/memory/tegra/tegra30.c
+++ b/drivers/memory/tegra/tegra30.c
@@ -960,6 +960,36 @@ static const struct tegra_smmu_soc tegra30_smmu_soc = {
960 .num_asids = 4, 960 .num_asids = 4,
961}; 961};
962 962
963#define TEGRA30_MC_RESET(_name, _control, _status, _bit) \
964 { \
965 .name = #_name, \
966 .id = TEGRA30_MC_RESET_##_name, \
967 .control = _control, \
968 .status = _status, \
969 .bit = _bit, \
970 }
971
972static const struct tegra_mc_reset tegra30_mc_resets[] = {
973 TEGRA30_MC_RESET(AFI, 0x200, 0x204, 0),
974 TEGRA30_MC_RESET(AVPC, 0x200, 0x204, 1),
975 TEGRA30_MC_RESET(DC, 0x200, 0x204, 2),
976 TEGRA30_MC_RESET(DCB, 0x200, 0x204, 3),
977 TEGRA30_MC_RESET(EPP, 0x200, 0x204, 4),
978 TEGRA30_MC_RESET(2D, 0x200, 0x204, 5),
979 TEGRA30_MC_RESET(HC, 0x200, 0x204, 6),
980 TEGRA30_MC_RESET(HDA, 0x200, 0x204, 7),
981 TEGRA30_MC_RESET(ISP, 0x200, 0x204, 8),
982 TEGRA30_MC_RESET(MPCORE, 0x200, 0x204, 9),
983 TEGRA30_MC_RESET(MPCORELP, 0x200, 0x204, 10),
984 TEGRA30_MC_RESET(MPE, 0x200, 0x204, 11),
985 TEGRA30_MC_RESET(3D, 0x200, 0x204, 12),
986 TEGRA30_MC_RESET(3D2, 0x200, 0x204, 13),
987 TEGRA30_MC_RESET(PPCS, 0x200, 0x204, 14),
988 TEGRA30_MC_RESET(SATA, 0x200, 0x204, 15),
989 TEGRA30_MC_RESET(VDE, 0x200, 0x204, 16),
990 TEGRA30_MC_RESET(VI, 0x200, 0x204, 17),
991};
992
963const struct tegra_mc_soc tegra30_mc_soc = { 993const struct tegra_mc_soc tegra30_mc_soc = {
964 .clients = tegra30_mc_clients, 994 .clients = tegra30_mc_clients,
965 .num_clients = ARRAY_SIZE(tegra30_mc_clients), 995 .num_clients = ARRAY_SIZE(tegra30_mc_clients),
@@ -967,4 +997,9 @@ const struct tegra_mc_soc tegra30_mc_soc = {
967 .atom_size = 16, 997 .atom_size = 16,
968 .client_id_mask = 0x7f, 998 .client_id_mask = 0x7f,
969 .smmu = &tegra30_smmu_soc, 999 .smmu = &tegra30_smmu_soc,
1000 .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
1001 MC_INT_DECERR_EMEM,
1002 .reset_ops = &terga_mc_reset_ops_common,
1003 .resets = tegra30_mc_resets,
1004 .num_resets = ARRAY_SIZE(tegra30_mc_resets),
970}; 1005};
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c
deleted file mode 100644
index cc309a05289a..000000000000
--- a/drivers/memory/tegra20-mc.c
+++ /dev/null
@@ -1,254 +0,0 @@
1/*
2 * Tegra20 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 "tegra20-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_INVALID_GART_PAGE BIT(MC_INT_ERR_SHIFT + 1)
37#define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2)
38#define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3)
39
40#define MC_GART_ERROR_REQ 0x30
41#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
42#define MC_SECURITY_VIOLATION_STATUS 0x74
43
44#define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */
45
46#define MC_CLIENT_ID_MASK 0x3f
47
48#define NUM_MC_REG_BANKS 2
49
50struct tegra20_mc {
51 void __iomem *regs[NUM_MC_REG_BANKS];
52 struct device *dev;
53};
54
55static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs)
56{
57 u32 val = 0;
58
59 if (offs < 0x24)
60 val = readl(mc->regs[0] + offs);
61 else if (offs < 0x400)
62 val = readl(mc->regs[1] + offs - 0x3c);
63
64 return val;
65}
66
67static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs)
68{
69 if (offs < 0x24)
70 writel(val, mc->regs[0] + offs);
71 else if (offs < 0x400)
72 writel(val, mc->regs[1] + offs - 0x3c);
73}
74
75static const char * const tegra20_mc_client[] = {
76 "cbr_display0a",
77 "cbr_display0ab",
78 "cbr_display0b",
79 "cbr_display0bb",
80 "cbr_display0c",
81 "cbr_display0cb",
82 "cbr_display1b",
83 "cbr_display1bb",
84 "cbr_eppup",
85 "cbr_g2pr",
86 "cbr_g2sr",
87 "cbr_mpeunifbr",
88 "cbr_viruv",
89 "csr_avpcarm7r",
90 "csr_displayhc",
91 "csr_displayhcb",
92 "csr_fdcdrd",
93 "csr_g2dr",
94 "csr_host1xdmar",
95 "csr_host1xr",
96 "csr_idxsrd",
97 "csr_mpcorer",
98 "csr_mpe_ipred",
99 "csr_mpeamemrd",
100 "csr_mpecsrd",
101 "csr_ppcsahbdmar",
102 "csr_ppcsahbslvr",
103 "csr_texsrd",
104 "csr_vdebsevr",
105 "csr_vdember",
106 "csr_vdemcer",
107 "csr_vdetper",
108 "cbw_eppu",
109 "cbw_eppv",
110 "cbw_eppy",
111 "cbw_mpeunifbw",
112 "cbw_viwsb",
113 "cbw_viwu",
114 "cbw_viwv",
115 "cbw_viwy",
116 "ccw_g2dw",
117 "csw_avpcarm7w",
118 "csw_fdcdwr",
119 "csw_host1xw",
120 "csw_ispw",
121 "csw_mpcorew",
122 "csw_mpecswr",
123 "csw_ppcsahbdmaw",
124 "csw_ppcsahbslvw",
125 "csw_vdebsevw",
126 "csw_vdembew",
127 "csw_vdetpmw",
128};
129
130static void tegra20_mc_decode(struct tegra20_mc *mc, int n)
131{
132 u32 addr, req;
133 const char *client = "Unknown";
134 int idx, cid;
135 const struct reg_info {
136 u32 offset;
137 u32 write_bit; /* 0=READ, 1=WRITE */
138 int cid_shift;
139 char *message;
140 } reg[] = {
141 {
142 .offset = MC_DECERR_EMEM_OTHERS_STATUS,
143 .write_bit = 31,
144 .message = "MC_DECERR",
145 },
146 {
147 .offset = MC_GART_ERROR_REQ,
148 .cid_shift = 1,
149 .message = "MC_GART_ERR",
150
151 },
152 {
153 .offset = MC_SECURITY_VIOLATION_STATUS,
154 .write_bit = 31,
155 .message = "MC_SECURITY_ERR",
156 },
157 };
158
159 idx = n - MC_INT_ERR_SHIFT;
160 if ((idx < 0) || (idx >= ARRAY_SIZE(reg))) {
161 dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n",
162 BIT(n));
163 return;
164 }
165
166 req = mc_readl(mc, reg[idx].offset);
167 cid = (req >> reg[idx].cid_shift) & MC_CLIENT_ID_MASK;
168 if (cid < ARRAY_SIZE(tegra20_mc_client))
169 client = tegra20_mc_client[cid];
170
171 addr = mc_readl(mc, reg[idx].offset + sizeof(u32));
172
173 dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s)\n",
174 reg[idx].message, req, addr, client,
175 (req & BIT(reg[idx].write_bit)) ? "write" : "read",
176 (reg[idx].offset == MC_SECURITY_VIOLATION_STATUS) ?
177 ((req & SECURITY_VIOLATION_TYPE) ?
178 "carveout" : "trustzone") : "");
179}
180
181static const struct of_device_id tegra20_mc_of_match[] = {
182 { .compatible = "nvidia,tegra20-mc", },
183 {},
184};
185
186static irqreturn_t tegra20_mc_isr(int irq, void *data)
187{
188 u32 stat, mask, bit;
189 struct tegra20_mc *mc = data;
190
191 stat = mc_readl(mc, MC_INTSTATUS);
192 mask = mc_readl(mc, MC_INTMASK);
193 mask &= stat;
194 if (!mask)
195 return IRQ_NONE;
196 while ((bit = ffs(mask)) != 0) {
197 tegra20_mc_decode(mc, bit - 1);
198 mask &= ~BIT(bit - 1);
199 }
200
201 mc_writel(mc, stat, MC_INTSTATUS);
202 return IRQ_HANDLED;
203}
204
205static int tegra20_mc_probe(struct platform_device *pdev)
206{
207 struct resource *irq;
208 struct tegra20_mc *mc;
209 int i, err;
210 u32 intmask;
211
212 mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
213 if (!mc)
214 return -ENOMEM;
215 mc->dev = &pdev->dev;
216
217 for (i = 0; i < ARRAY_SIZE(mc->regs); i++) {
218 struct resource *res;
219
220 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
221 mc->regs[i] = devm_ioremap_resource(&pdev->dev, res);
222 if (IS_ERR(mc->regs[i]))
223 return PTR_ERR(mc->regs[i]);
224 }
225
226 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
227 if (!irq)
228 return -ENODEV;
229 err = devm_request_irq(&pdev->dev, irq->start, tegra20_mc_isr,
230 IRQF_SHARED, dev_name(&pdev->dev), mc);
231 if (err)
232 return -ENODEV;
233
234 platform_set_drvdata(pdev, mc);
235
236 intmask = MC_INT_INVALID_GART_PAGE |
237 MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION;
238 mc_writel(mc, intmask, MC_INTMASK);
239 return 0;
240}
241
242static struct platform_driver tegra20_mc_driver = {
243 .probe = tegra20_mc_probe,
244 .driver = {
245 .name = DRV_NAME,
246 .of_match_table = tegra20_mc_of_match,
247 },
248};
249module_platform_driver(tegra20_mc_driver);
250
251MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
252MODULE_DESCRIPTION("Tegra20 MC driver");
253MODULE_LICENSE("GPL v2");
254MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/include/dt-bindings/memory/tegra114-mc.h b/include/dt-bindings/memory/tegra114-mc.h
index 27c8386987ff..dfe99c8a5ba5 100644
--- a/include/dt-bindings/memory/tegra114-mc.h
+++ b/include/dt-bindings/memory/tegra114-mc.h
@@ -23,4 +23,21 @@
23#define TEGRA_SWGROUP_EMUCIF 18 23#define TEGRA_SWGROUP_EMUCIF 18
24#define TEGRA_SWGROUP_TSEC 19 24#define TEGRA_SWGROUP_TSEC 19
25 25
26#define TEGRA114_MC_RESET_AVPC 0
27#define TEGRA114_MC_RESET_DC 1
28#define TEGRA114_MC_RESET_DCB 2
29#define TEGRA114_MC_RESET_EPP 3
30#define TEGRA114_MC_RESET_2D 4
31#define TEGRA114_MC_RESET_HC 5
32#define TEGRA114_MC_RESET_HDA 6
33#define TEGRA114_MC_RESET_ISP 7
34#define TEGRA114_MC_RESET_MPCORE 8
35#define TEGRA114_MC_RESET_MPCORELP 9
36#define TEGRA114_MC_RESET_MPE 10
37#define TEGRA114_MC_RESET_3D 11
38#define TEGRA114_MC_RESET_3D2 12
39#define TEGRA114_MC_RESET_PPCS 13
40#define TEGRA114_MC_RESET_VDE 14
41#define TEGRA114_MC_RESET_VI 15
42
26#endif 43#endif
diff --git a/include/dt-bindings/memory/tegra124-mc.h b/include/dt-bindings/memory/tegra124-mc.h
index f534d7c06019..186e6b7e9b35 100644
--- a/include/dt-bindings/memory/tegra124-mc.h
+++ b/include/dt-bindings/memory/tegra124-mc.h
@@ -29,4 +29,29 @@
29#define TEGRA_SWGROUP_VIC 24 29#define TEGRA_SWGROUP_VIC 24
30#define TEGRA_SWGROUP_VI 25 30#define TEGRA_SWGROUP_VI 25
31 31
32#define TEGRA124_MC_RESET_AFI 0
33#define TEGRA124_MC_RESET_AVPC 1
34#define TEGRA124_MC_RESET_DC 2
35#define TEGRA124_MC_RESET_DCB 3
36#define TEGRA124_MC_RESET_HC 4
37#define TEGRA124_MC_RESET_HDA 5
38#define TEGRA124_MC_RESET_ISP2 6
39#define TEGRA124_MC_RESET_MPCORE 7
40#define TEGRA124_MC_RESET_MPCORELP 8
41#define TEGRA124_MC_RESET_MSENC 9
42#define TEGRA124_MC_RESET_PPCS 10
43#define TEGRA124_MC_RESET_SATA 11
44#define TEGRA124_MC_RESET_VDE 12
45#define TEGRA124_MC_RESET_VI 13
46#define TEGRA124_MC_RESET_VIC 14
47#define TEGRA124_MC_RESET_XUSB_HOST 15
48#define TEGRA124_MC_RESET_XUSB_DEV 16
49#define TEGRA124_MC_RESET_TSEC 17
50#define TEGRA124_MC_RESET_SDMMC1 18
51#define TEGRA124_MC_RESET_SDMMC2 19
52#define TEGRA124_MC_RESET_SDMMC3 20
53#define TEGRA124_MC_RESET_SDMMC4 21
54#define TEGRA124_MC_RESET_ISP2B 22
55#define TEGRA124_MC_RESET_GPU 23
56
32#endif 57#endif
diff --git a/include/dt-bindings/memory/tegra20-mc.h b/include/dt-bindings/memory/tegra20-mc.h
new file mode 100644
index 000000000000..35e131eee198
--- /dev/null
+++ b/include/dt-bindings/memory/tegra20-mc.h
@@ -0,0 +1,21 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef DT_BINDINGS_MEMORY_TEGRA20_MC_H
3#define DT_BINDINGS_MEMORY_TEGRA20_MC_H
4
5#define TEGRA20_MC_RESET_AVPC 0
6#define TEGRA20_MC_RESET_DC 1
7#define TEGRA20_MC_RESET_DCB 2
8#define TEGRA20_MC_RESET_EPP 3
9#define TEGRA20_MC_RESET_2D 4
10#define TEGRA20_MC_RESET_HC 5
11#define TEGRA20_MC_RESET_ISP 6
12#define TEGRA20_MC_RESET_MPCORE 7
13#define TEGRA20_MC_RESET_MPEA 8
14#define TEGRA20_MC_RESET_MPEB 9
15#define TEGRA20_MC_RESET_MPEC 10
16#define TEGRA20_MC_RESET_3D 11
17#define TEGRA20_MC_RESET_PPCS 12
18#define TEGRA20_MC_RESET_VDE 13
19#define TEGRA20_MC_RESET_VI 14
20
21#endif
diff --git a/include/dt-bindings/memory/tegra210-mc.h b/include/dt-bindings/memory/tegra210-mc.h
index 4490f7cf4772..cacf05617e03 100644
--- a/include/dt-bindings/memory/tegra210-mc.h
+++ b/include/dt-bindings/memory/tegra210-mc.h
@@ -34,4 +34,35 @@
34#define TEGRA_SWGROUP_ETR 29 34#define TEGRA_SWGROUP_ETR 29
35#define TEGRA_SWGROUP_TSECB 30 35#define TEGRA_SWGROUP_TSECB 30
36 36
37#define TEGRA210_MC_RESET_AFI 0
38#define TEGRA210_MC_RESET_AVPC 1
39#define TEGRA210_MC_RESET_DC 2
40#define TEGRA210_MC_RESET_DCB 3
41#define TEGRA210_MC_RESET_HC 4
42#define TEGRA210_MC_RESET_HDA 5
43#define TEGRA210_MC_RESET_ISP2 6
44#define TEGRA210_MC_RESET_MPCORE 7
45#define TEGRA210_MC_RESET_NVENC 8
46#define TEGRA210_MC_RESET_PPCS 9
47#define TEGRA210_MC_RESET_SATA 10
48#define TEGRA210_MC_RESET_VI 11
49#define TEGRA210_MC_RESET_VIC 12
50#define TEGRA210_MC_RESET_XUSB_HOST 13
51#define TEGRA210_MC_RESET_XUSB_DEV 14
52#define TEGRA210_MC_RESET_A9AVP 15
53#define TEGRA210_MC_RESET_TSEC 16
54#define TEGRA210_MC_RESET_SDMMC1 17
55#define TEGRA210_MC_RESET_SDMMC2 18
56#define TEGRA210_MC_RESET_SDMMC3 19
57#define TEGRA210_MC_RESET_SDMMC4 20
58#define TEGRA210_MC_RESET_ISP2B 21
59#define TEGRA210_MC_RESET_GPU 22
60#define TEGRA210_MC_RESET_NVDEC 23
61#define TEGRA210_MC_RESET_APE 24
62#define TEGRA210_MC_RESET_SE 25
63#define TEGRA210_MC_RESET_NVJPG 26
64#define TEGRA210_MC_RESET_AXIAP 27
65#define TEGRA210_MC_RESET_ETR 28
66#define TEGRA210_MC_RESET_TSECB 29
67
37#endif 68#endif
diff --git a/include/dt-bindings/memory/tegra30-mc.h b/include/dt-bindings/memory/tegra30-mc.h
index 3cac81919023..169f005fbc78 100644
--- a/include/dt-bindings/memory/tegra30-mc.h
+++ b/include/dt-bindings/memory/tegra30-mc.h
@@ -22,4 +22,23 @@
22#define TEGRA_SWGROUP_MPCORE 17 22#define TEGRA_SWGROUP_MPCORE 17
23#define TEGRA_SWGROUP_ISP 18 23#define TEGRA_SWGROUP_ISP 18
24 24
25#define TEGRA30_MC_RESET_AFI 0
26#define TEGRA30_MC_RESET_AVPC 1
27#define TEGRA30_MC_RESET_DC 2
28#define TEGRA30_MC_RESET_DCB 3
29#define TEGRA30_MC_RESET_EPP 4
30#define TEGRA30_MC_RESET_2D 5
31#define TEGRA30_MC_RESET_HC 6
32#define TEGRA30_MC_RESET_HDA 7
33#define TEGRA30_MC_RESET_ISP 8
34#define TEGRA30_MC_RESET_MPCORE 9
35#define TEGRA30_MC_RESET_MPCORELP 10
36#define TEGRA30_MC_RESET_MPE 11
37#define TEGRA30_MC_RESET_3D 12
38#define TEGRA30_MC_RESET_3D2 13
39#define TEGRA30_MC_RESET_PPCS 14
40#define TEGRA30_MC_RESET_SATA 15
41#define TEGRA30_MC_RESET_VDE 16
42#define TEGRA30_MC_RESET_VI 17
43
25#endif 44#endif
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index 233bae954970..b43f37fea096 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -9,6 +9,7 @@
9#ifndef __SOC_TEGRA_MC_H__ 9#ifndef __SOC_TEGRA_MC_H__
10#define __SOC_TEGRA_MC_H__ 10#define __SOC_TEGRA_MC_H__
11 11
12#include <linux/reset-controller.h>
12#include <linux/types.h> 13#include <linux/types.h>
13 14
14struct clk; 15struct clk;
@@ -95,6 +96,30 @@ static inline void tegra_smmu_remove(struct tegra_smmu *smmu)
95} 96}
96#endif 97#endif
97 98
99struct tegra_mc_reset {
100 const char *name;
101 unsigned long id;
102 unsigned int control;
103 unsigned int status;
104 unsigned int reset;
105 unsigned int bit;
106};
107
108struct tegra_mc_reset_ops {
109 int (*hotreset_assert)(struct tegra_mc *mc,
110 const struct tegra_mc_reset *rst);
111 int (*hotreset_deassert)(struct tegra_mc *mc,
112 const struct tegra_mc_reset *rst);
113 int (*block_dma)(struct tegra_mc *mc,
114 const struct tegra_mc_reset *rst);
115 bool (*dma_idling)(struct tegra_mc *mc,
116 const struct tegra_mc_reset *rst);
117 int (*unblock_dma)(struct tegra_mc *mc,
118 const struct tegra_mc_reset *rst);
119 int (*reset_status)(struct tegra_mc *mc,
120 const struct tegra_mc_reset *rst);
121};
122
98struct tegra_mc_soc { 123struct tegra_mc_soc {
99 const struct tegra_mc_client *clients; 124 const struct tegra_mc_client *clients;
100 unsigned int num_clients; 125 unsigned int num_clients;
@@ -108,12 +133,18 @@ struct tegra_mc_soc {
108 u8 client_id_mask; 133 u8 client_id_mask;
109 134
110 const struct tegra_smmu_soc *smmu; 135 const struct tegra_smmu_soc *smmu;
136
137 u32 intmask;
138
139 const struct tegra_mc_reset_ops *reset_ops;
140 const struct tegra_mc_reset *resets;
141 unsigned int num_resets;
111}; 142};
112 143
113struct tegra_mc { 144struct tegra_mc {
114 struct device *dev; 145 struct device *dev;
115 struct tegra_smmu *smmu; 146 struct tegra_smmu *smmu;
116 void __iomem *regs; 147 void __iomem *regs, *regs2;
117 struct clk *clk; 148 struct clk *clk;
118 int irq; 149 int irq;
119 150
@@ -122,6 +153,10 @@ struct tegra_mc {
122 153
123 struct tegra_mc_timing *timings; 154 struct tegra_mc_timing *timings;
124 unsigned int num_timings; 155 unsigned int num_timings;
156
157 struct reset_controller_dev reset;
158
159 spinlock_t lock;
125}; 160};
126 161
127void tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate); 162void tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);