Tegra Memory Controller(MC) driver for Tegra20
Added to support MC General interrupts, mainly for IOMMU(GART).
Signed-off-by: Hiroshi DOYU <[email protected]>
---
.../bindings/arm/tegra/nvidia,tegra20-mc.txt | 16 ++
arch/arm/mach-tegra/Kconfig | 2 +
drivers/memory/Kconfig | 4 +
drivers/memory/Makefile | 1 +
drivers/memory/tegra20-mc.c | 262 ++++++++++++++++++++
5 files changed, 285 insertions(+), 0 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt
new file mode 100644
index 0000000..c25a0a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt
@@ -0,0 +1,16 @@
+NVIDIA Tegra20 MC(Memory Controller)
+
+Required properties:
+- compatible : "nvidia,tegra20-mc"
+- reg : Should contain 2 register ranges(address and length); see the
+ example below. Note that the MC registers are interleaved with the
+ GART registers, and hence must be represented as multiple ranges.
+- interrupts : Should contain MC General interrupt.
+
+Example:
+ mc {
+ compatible = "nvidia,tegra20-mc";
+ reg = <0x7000f000 0x024
+ 0x7000f03c 0x3c4>;
+ interrupts = <0 77 0x04>;
+ };
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 6a113a9..abaf5d0 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -20,6 +20,8 @@ config ARCH_TEGRA_2x_SOC
select PL310_ERRATA_727915 if CACHE_L2X0
select PL310_ERRATA_769419 if CACHE_L2X0
select CPU_FREQ_TABLE if CPU_FREQ
+ select MEMORY
+ select TEGRA20_MC
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index e0b3156..ebade16 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -20,4 +20,8 @@ config TI_EMIF
parameters and other settings during frequency, voltage and
temperature changes
+config TEGRA20_MC
+ bool
+ depends on ARCH_TEGRA_2x_SOC
+
endif
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index e27f80b..1f58518 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_TI_EMIF) += emif.o
+obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c
new file mode 100644
index 0000000..c0bfffa
--- /dev/null
+++ b/drivers/memory/tegra20-mc.c
@@ -0,0 +1,262 @@
+/*
+ * Tegra20 Memory Controller
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ratelimit.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#define DRV_NAME "tegra20-mc"
+
+#define MC_INTSTATUS 0x0
+#define MC_INTMASK 0x4
+
+#define MC_INT_ERR_SHIFT 6
+#define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT)
+#define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT)
+#define MC_INT_INVALID_GART_PAGE BIT(MC_INT_ERR_SHIFT + 1)
+#define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2)
+#define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3)
+
+#define MC_GART_ERROR_REQ 0x30
+#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
+#define MC_SECURITY_VIOLATION_STATUS 0x74
+
+#define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */
+
+#define MC_CLIENT_ID_MASK 0x3f
+
+#define NUM_MC_REG_BANKS 2
+
+struct tegra20_mc {
+ void __iomem *regs[NUM_MC_REG_BANKS];
+ struct device *dev;
+};
+
+static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs)
+{
+ if (offs < 0x24)
+ return readl(mc->regs[0] + offs);
+ BUG_ON(offs < 0x3c);
+ if (offs < 0x400)
+ return readl(mc->regs[1] + offs - 0x3c);
+ BUG();
+}
+
+static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs)
+{
+ if (offs < 0x24) {
+ writel(val, mc->regs[0] + offs);
+ return;
+ }
+ BUG_ON(offs < 0x3c);
+ if (offs < 0x400) {
+ writel(val, mc->regs[1] + offs - 0x3c);
+ return;
+ }
+ BUG();
+}
+
+static const char * const tegra20_mc_client[] = {
+ "cbr_display0a",
+ "cbr_display0ab",
+ "cbr_display0b",
+ "cbr_display0bb",
+ "cbr_display0c",
+ "cbr_display0cb",
+ "cbr_display1b",
+ "cbr_display1bb",
+ "cbr_eppup",
+ "cbr_g2pr",
+ "cbr_g2sr",
+ "cbr_mpeunifbr",
+ "cbr_viruv",
+ "csr_avpcarm7r",
+ "csr_displayhc",
+ "csr_displayhcb",
+ "csr_fdcdrd",
+ "csr_g2dr",
+ "csr_host1xdmar",
+ "csr_host1xr",
+ "csr_idxsrd",
+ "csr_mpcorer",
+ "csr_mpe_ipred",
+ "csr_mpeamemrd",
+ "csr_mpecsrd",
+ "csr_ppcsahbdmar",
+ "csr_ppcsahbslvr",
+ "csr_texsrd",
+ "csr_vdebsevr",
+ "csr_vdember",
+ "csr_vdemcer",
+ "csr_vdetper",
+ "cbw_eppu",
+ "cbw_eppv",
+ "cbw_eppy",
+ "cbw_mpeunifbw",
+ "cbw_viwsb",
+ "cbw_viwu",
+ "cbw_viwv",
+ "cbw_viwy",
+ "ccw_g2dw",
+ "csw_avpcarm7w",
+ "csw_fdcdwr",
+ "csw_host1xw",
+ "csw_ispw",
+ "csw_mpcorew",
+ "csw_mpecswr",
+ "csw_ppcsahbdmaw",
+ "csw_ppcsahbslvw",
+ "csw_vdebsevw",
+ "csw_vdembew",
+ "csw_vdetpmw",
+};
+
+static void tegra20_mc_decode(struct tegra20_mc *mc, int n)
+{
+ u32 addr, req;
+ const char *client = "Unknown";
+ int idx, cid;
+ const struct reg_info {
+ u32 offset;
+ u32 write_bit; /* 0=READ, 1=WRITE */
+ int cid_shift;
+ char *message;
+ } reg[] = {
+ {
+ .offset = MC_DECERR_EMEM_OTHERS_STATUS,
+ .write_bit = 31,
+ .message = "MC_DECERR",
+ },
+ {
+ .offset = MC_GART_ERROR_REQ,
+ .cid_shift = 1,
+ .message = "MC_GART_ERR",
+
+ },
+ {
+ .offset = MC_SECURITY_VIOLATION_STATUS,
+ .write_bit = 31,
+ .message = "MC_SECURITY_ERR",
+ },
+ };
+
+ idx = n - MC_INT_ERR_SHIFT;
+ if ((idx < 0) || (idx >= ARRAY_SIZE(reg))) {
+ pr_err_ratelimited("Unknown interrupt status %08lx\n", BIT(n));
+ return;
+ }
+
+ req = mc_readl(mc, reg[idx].offset);
+ cid = (req >> reg[idx].cid_shift) & MC_CLIENT_ID_MASK;
+ if (cid < ARRAY_SIZE(tegra20_mc_client))
+ client = tegra20_mc_client[cid];
+
+ addr = mc_readl(mc, reg[idx].offset + sizeof(u32));
+
+ pr_err_ratelimited("%s (0x%08x): 0x%08x %s (%s %s)\n",
+ reg[idx].message, req, addr, client,
+ (req & BIT(reg[idx].write_bit)) ? "write" : "read",
+ (reg[idx].offset == MC_SECURITY_VIOLATION_STATUS) ?
+ ((req & SECURITY_VIOLATION_TYPE) ?
+ "carveout" : "trustzone") : "");
+}
+
+static const struct of_device_id tegra20_mc_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-mc", },
+ {},
+};
+
+static irqreturn_t tegra20_mc_isr(int irq, void *data)
+{
+ u32 stat, mask, bit;
+ struct tegra20_mc *mc = data;
+
+ stat = mc_readl(mc, MC_INTSTATUS);
+ mask = mc_readl(mc, MC_INTMASK);
+ mask &= stat;
+ if (!mask)
+ return IRQ_NONE;
+ while ((bit = ffs(mask)) != 0)
+ tegra20_mc_decode(mc, bit - 1);
+ mc_writel(mc, stat, MC_INTSTATUS);
+ return IRQ_HANDLED;
+}
+
+static int __devinit tegra20_mc_probe(struct platform_device *pdev)
+{
+ struct resource *irq;
+ struct tegra20_mc *mc;
+ int i, err;
+ u32 intmask;
+
+ mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
+ if (!mc)
+ return -ENOMEM;
+ mc->dev = &pdev->dev;
+
+ for (i = 0; i < ARRAY_SIZE(mc->regs); i++) {
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res)
+ return -ENODEV;
+ mc->regs[i] = devm_request_and_ioremap(&pdev->dev, res);
+ if (!mc->regs[i])
+ return -EBUSY;
+ }
+
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq)
+ return -ENODEV;
+ err = devm_request_irq(&pdev->dev, irq->start, tegra20_mc_isr,
+ IRQF_SHARED, dev_name(&pdev->dev), mc);
+ if (err)
+ return -ENODEV;
+
+ platform_set_drvdata(pdev, mc);
+
+ intmask = MC_INT_INVALID_GART_PAGE |
+ MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION;
+ mc_writel(mc, intmask, MC_INTMASK);
+ return 0;
+}
+
+static int __devexit tegra20_mc_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver tegra20_mc_driver = {
+ .probe = tegra20_mc_probe,
+ .remove = __devexit_p(tegra20_mc_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra20_mc_of_match,
+ },
+};
+module_platform_driver(tegra20_mc_driver);
+
+MODULE_AUTHOR("Hiroshi DOYU <[email protected]>");
+MODULE_DESCRIPTION("Tegra20 MC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
--
1.7.5.4
Add Tegra MC(Memory Controller) nodes for tegra20.dtsi.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
arch/arm/boot/dts/tegra20.dtsi | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 24129fb..548b42e 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -211,5 +211,12 @@
compatible = "nvidia,tegra20-ahb";
reg = <0x6000c004 0x10c>; /* AHB Arbitration + Gizmo Controller */
};
+
+ mc {
+ compatible = "nvidia,tegra20-mc";
+ reg = <0x7000f000 0x024
+ 0x7000f03c 0x3c4>;
+ interrupts = <0 77 0x04>;
+ };
};
--
1.7.5.4
Tegra Memory Controller(MC) driver for Tegra30
Added to support MC General interrupts, mainly for IOMMU(SMMU).
Signed-off-by: Hiroshi DOYU <[email protected]>
---
.../bindings/arm/tegra/nvidia,tegra30-mc.txt | 18 +
arch/arm/mach-tegra/Kconfig | 2 +
drivers/memory/Kconfig | 4 +
drivers/memory/Makefile | 1 +
drivers/memory/tegra30-mc.c | 391 ++++++++++++++++++++
5 files changed, 416 insertions(+), 0 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
new file mode 100644
index 0000000..e47e73f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
@@ -0,0 +1,18 @@
+NVIDIA Tegra30 MC(Memory Controller)
+
+Required properties:
+- compatible : "nvidia,tegra30-mc"
+- reg : Should contain 4 register ranges(address and length); see the
+ example below. Note that the MC registers are interleaved with the
+ SMMU registers, and hence must be represented as multiple ranges.
+- interrupts : Should contain MC General interrupt.
+
+Example:
+ mc {
+ compatible = "nvidia,tegra30-mc";
+ reg = <0x7000f000 0x010
+ 0x7000f03c 0x1b4
+ 0x7000f200 0x028
+ 0x7000f284 0x17c>;
+ interrupts = <0 77 0x04>;
+ };
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index abaf5d0..16fe065 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -43,6 +43,8 @@ config ARCH_TEGRA_3x_SOC
select ARM_ERRATA_764369
select PL310_ERRATA_769419 if CACHE_L2X0
select CPU_FREQ_TABLE if CPU_FREQ
+ select MEMORY
+ select TEGRA30_MC
help
Support for NVIDIA Tegra T30 processor family, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index ebade16..42e6d66 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -24,4 +24,8 @@ config TEGRA20_MC
bool
depends on ARCH_TEGRA_2x_SOC
+config TEGRA30_MC
+ bool
+ depends on ARCH_TEGRA_3x_SOC
+
endif
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 1f58518..42b3ce9 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_TI_EMIF) += emif.o
obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
+obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
new file mode 100644
index 0000000..c982125
--- /dev/null
+++ b/drivers/memory/tegra30-mc.c
@@ -0,0 +1,391 @@
+/*
+ * Tegra30 Memory Controller
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ratelimit.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#define DRV_NAME "tegra30-mc"
+
+#define MC_INTSTATUS 0x0
+#define MC_INTMASK 0x4
+
+#define MC_INT_ERR_SHIFT 6
+#define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT)
+#define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT)
+#define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2)
+#define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3)
+#define MC_INT_INVALID_SMMU_PAGE BIT(MC_INT_ERR_SHIFT + 4)
+
+#define MC_ERR_STATUS 0x8
+#define MC_ERR_ADR 0xc
+
+#define MC_ERR_TYPE_SHIFT 28
+#define MC_ERR_TYPE_MASK (7 << MC_ERR_TYPE_SHIFT)
+#define MC_ERR_TYPE_DECERR_EMEM 2
+#define MC_ERR_TYPE_SECURITY_TRUSTZONE 3
+#define MC_ERR_TYPE_SECURITY_CARVEOUT 4
+#define MC_ERR_TYPE_INVALID_SMMU_PAGE 6
+
+#define MC_ERR_INVALID_SMMU_PAGE_SHIFT 25
+#define MC_ERR_INVALID_SMMU_PAGE_MASK (7 << MC_ERR_INVALID_SMMU_PAGE_SHIFT)
+#define MC_ERR_RW_SHIFT 16
+#define MC_ERR_RW BIT(MC_ERR_RW_SHIFT)
+#define MC_ERR_SECURITY BIT(MC_ERR_RW_SHIFT + 1)
+
+#define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */
+
+#define MC_EMEM_ARB_CFG 0x90
+#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
+#define MC_EMEM_ARB_TIMING_RCD 0x98
+#define MC_EMEM_ARB_TIMING_RP 0x9c
+#define MC_EMEM_ARB_TIMING_RC 0xa0
+#define MC_EMEM_ARB_TIMING_RAS 0xa4
+#define MC_EMEM_ARB_TIMING_FAW 0xa8
+#define MC_EMEM_ARB_TIMING_RRD 0xac
+#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
+#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
+#define MC_EMEM_ARB_TIMING_R2R 0xb8
+#define MC_EMEM_ARB_TIMING_W2W 0xbc
+#define MC_EMEM_ARB_TIMING_R2W 0xc0
+#define MC_EMEM_ARB_TIMING_W2R 0xc4
+
+#define MC_EMEM_ARB_DA_TURNS 0xd0
+#define MC_EMEM_ARB_DA_COVERS 0xd4
+#define MC_EMEM_ARB_MISC0 0xd8
+#define MC_EMEM_ARB_MISC1 0xdc
+
+#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
+#define MC_EMEM_ARB_OVERRIDE 0xe8
+
+#define MC_TIMING_CONTROL 0xfc
+
+#define MC_CLIENT_ID_MASK 0x7f
+
+#define NUM_MC_REG_BANKS 4
+
+struct tegra30_mc {
+ void __iomem *regs[NUM_MC_REG_BANKS];
+ struct device *dev;
+ u32 ctx[0];
+};
+
+static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs)
+{
+ if (offs < 0x10)
+ return readl(mc->regs[0] + offs);
+ BUG_ON(offs < 0x3c);
+ if (offs < 0x1f0)
+ return readl(mc->regs[1] + offs - 0x3c);
+ BUG_ON(offs < 0x200);
+ if (offs < 0x228)
+ return readl(mc->regs[2] + offs - 0x200);
+ BUG_ON(offs < 0x284);
+ if (offs < 0x400)
+ return readl(mc->regs[3] + offs - 0x284);
+ BUG();
+}
+
+static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs)
+{
+ if (offs < 0x10) {
+ writel(val, mc->regs[0] + offs);
+ return;
+ }
+ BUG_ON(offs < 0x3c);
+ if (offs < 0x1f0) {
+ writel(val, mc->regs[1] + offs - 0x3c);
+ return;
+ }
+ BUG_ON(offs < 0x200);
+ if (offs < 0x228) {
+ writel(val, mc->regs[2] + offs - 0x200);
+ return;
+ }
+ BUG_ON(offs < 0x284);
+ if (offs < 0x400) {
+ writel(val, mc->regs[3] + offs - 0x284);
+ return;
+ }
+ BUG();
+}
+
+static const char * const tegra30_mc_client[] = {
+ "csr_ptcr",
+ "cbr_display0a",
+ "cbr_display0ab",
+ "cbr_display0b",
+ "cbr_display0bb",
+ "cbr_display0c",
+ "cbr_display0cb",
+ "cbr_display1b",
+ "cbr_display1bb",
+ "cbr_eppup",
+ "cbr_g2pr",
+ "cbr_g2sr",
+ "cbr_mpeunifbr",
+ "cbr_viruv",
+ "csr_afir",
+ "csr_avpcarm7r",
+ "csr_displayhc",
+ "csr_displayhcb",
+ "csr_fdcdrd",
+ "csr_fdcdrd2",
+ "csr_g2dr",
+ "csr_hdar",
+ "csr_host1xdmar",
+ "csr_host1xr",
+ "csr_idxsrd",
+ "csr_idxsrd2",
+ "csr_mpe_ipred",
+ "csr_mpeamemrd",
+ "csr_mpecsrd",
+ "csr_ppcsahbdmar",
+ "csr_ppcsahbslvr",
+ "csr_satar",
+ "csr_texsrd",
+ "csr_texsrd2",
+ "csr_vdebsevr",
+ "csr_vdember",
+ "csr_vdemcer",
+ "csr_vdetper",
+ "csr_mpcorelpr",
+ "csr_mpcorer",
+ "cbw_eppu",
+ "cbw_eppv",
+ "cbw_eppy",
+ "cbw_mpeunifbw",
+ "cbw_viwsb",
+ "cbw_viwu",
+ "cbw_viwv",
+ "cbw_viwy",
+ "ccw_g2dw",
+ "csw_afiw",
+ "csw_avpcarm7w",
+ "csw_fdcdwr",
+ "csw_fdcdwr2",
+ "csw_hdaw",
+ "csw_host1xw",
+ "csw_ispw",
+ "csw_mpcorelpw",
+ "csw_mpcorew",
+ "csw_mpecswr",
+ "csw_ppcsahbdmaw",
+ "csw_ppcsahbslvw",
+ "csw_sataw",
+ "csw_vdebsevw",
+ "csw_vdedbgw",
+ "csw_vdembew",
+ "csw_vdetpmw",
+};
+
+static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
+{
+ u32 err, addr;
+ const char * const mc_int_err[] = {
+ "MC_DECERR",
+ "Unknown",
+ "MC_SECURITY_ERR",
+ "MC_ARBITRATION_EMEM",
+ "MC_SMMU_ERR",
+ };
+ const char * const err_type[] = {
+ "Unknown",
+ "Unknown",
+ "DECERR_EMEM",
+ "SECURITY_TRUSTZONE",
+ "SECURITY_CARVEOUT",
+ "Unknown",
+ "INVALID_SMMU_PAGE",
+ "Unknown",
+ };
+ char attr[6];
+ int cid, perm, type, idx;
+ const char *client = "Unknown";
+
+ idx = n - MC_INT_ERR_SHIFT;
+ if ((idx < 0) || (idx >= ARRAY_SIZE(mc_int_err)) || (idx == 1)) {
+ pr_err_ratelimited("Unknown interrupt status %08lx\n", BIT(n));
+ return;
+ }
+
+ err = readl(mc + MC_ERR_STATUS);
+
+ type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT;
+ perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >>
+ MC_ERR_INVALID_SMMU_PAGE_SHIFT;
+ if (type == MC_ERR_TYPE_INVALID_SMMU_PAGE)
+ sprintf(attr, "%c-%c-%c",
+ (perm & BIT(2)) ? 'R' : '-',
+ (perm & BIT(1)) ? 'W' : '-',
+ (perm & BIT(0)) ? 'S' : '-');
+ else
+ attr[0] = '\0';
+
+ cid = err & MC_CLIENT_ID_MASK;
+ if (cid < ARRAY_SIZE(tegra30_mc_client))
+ client = tegra30_mc_client[cid];
+
+ addr = readl(mc + MC_ERR_ADR);
+
+ pr_err_ratelimited("%s (0x%08x): 0x%08x %s (%s %s %s %s)\n",
+ mc_int_err[idx], err, addr, client,
+ (err & MC_ERR_SECURITY) ? "secure" : "non-secure",
+ (err & MC_ERR_RW) ? "write" : "read",
+ err_type[type], attr);
+}
+
+static const u32 tegra30_mc_ctx[] = {
+ MC_EMEM_ARB_CFG,
+ MC_EMEM_ARB_OUTSTANDING_REQ,
+ MC_EMEM_ARB_TIMING_RCD,
+ MC_EMEM_ARB_TIMING_RP,
+ MC_EMEM_ARB_TIMING_RC,
+ MC_EMEM_ARB_TIMING_RAS,
+ MC_EMEM_ARB_TIMING_FAW,
+ MC_EMEM_ARB_TIMING_RRD,
+ MC_EMEM_ARB_TIMING_RAP2PRE,
+ MC_EMEM_ARB_TIMING_WAP2PRE,
+ MC_EMEM_ARB_TIMING_R2R,
+ MC_EMEM_ARB_TIMING_W2W,
+ MC_EMEM_ARB_TIMING_R2W,
+ MC_EMEM_ARB_TIMING_W2R,
+ MC_EMEM_ARB_DA_TURNS,
+ MC_EMEM_ARB_DA_COVERS,
+ MC_EMEM_ARB_MISC0,
+ MC_EMEM_ARB_MISC1,
+ MC_EMEM_ARB_RING3_THROTTLE,
+ MC_EMEM_ARB_OVERRIDE,
+ MC_INTMASK,
+};
+
+static int tegra30_mc_suspend(struct device *dev)
+{
+ int i;
+ struct tegra30_mc *mc = dev_get_drvdata(dev);
+
+ for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++)
+ mc->ctx[i] = mc_readl(mc, tegra30_mc_ctx[i]);
+ return 0;
+}
+
+static int tegra30_mc_resume(struct device *dev)
+{
+ int i;
+ struct tegra30_mc *mc = dev_get_drvdata(dev);
+
+ for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++)
+ mc_writel(mc, mc->ctx[i], tegra30_mc_ctx[i]);
+
+ mc_writel(mc, 1, MC_TIMING_CONTROL);
+ /* Read-back to ensure that write reached */
+ mc_readl(mc, MC_TIMING_CONTROL);
+ return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm,
+ tegra30_mc_suspend,
+ tegra30_mc_resume, NULL);
+
+static const struct of_device_id tegra30_mc_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra30-mc", },
+ {},
+};
+
+static irqreturn_t tegra30_mc_isr(int irq, void *data)
+{
+ u32 stat, mask, bit;
+ struct tegra30_mc *mc = data;
+
+ stat = mc_readl(mc, MC_INTSTATUS);
+ mask = mc_readl(mc, MC_INTMASK);
+ mask &= stat;
+ if (!mask)
+ return IRQ_NONE;
+ while ((bit = ffs(mask)) != 0)
+ tegra30_mc_decode(mc, bit - 1);
+ mc_writel(mc, stat, MC_INTSTATUS);
+ return IRQ_HANDLED;
+}
+
+static int __devinit tegra30_mc_probe(struct platform_device *pdev)
+{
+ struct resource *irq;
+ struct tegra30_mc *mc;
+ size_t bytes;
+ int err, i;
+ u32 intmask;
+
+ bytes = sizeof(*mc) + sizeof(u32) * ARRAY_SIZE(tegra30_mc_ctx);
+ mc = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL);
+ if (!mc)
+ return -ENOMEM;
+ mc->dev = &pdev->dev;
+
+ for (i = 0; i < ARRAY_SIZE(mc->regs); i++) {
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res)
+ return -ENODEV;
+ mc->regs[i] = devm_request_and_ioremap(&pdev->dev, res);
+ if (!mc->regs[i])
+ return -EBUSY;
+ }
+
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq)
+ return -ENODEV;
+ err = devm_request_irq(&pdev->dev, irq->start, tegra30_mc_isr,
+ IRQF_SHARED, dev_name(&pdev->dev), mc);
+ if (err)
+ return -ENODEV;
+
+ platform_set_drvdata(pdev, mc);
+
+ intmask = MC_INT_INVALID_SMMU_PAGE |
+ MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION;
+ mc_writel(mc, intmask, MC_INTMASK);
+ return 0;
+}
+
+static int __devexit tegra30_mc_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver tegra30_mc_driver = {
+ .probe = tegra30_mc_probe,
+ .remove = __devexit_p(tegra30_mc_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra30_mc_of_match,
+ .pm = &tegra30_mc_pm,
+ },
+};
+module_platform_driver(tegra30_mc_driver);
+
+MODULE_AUTHOR("Hiroshi DOYU <[email protected]>");
+MODULE_DESCRIPTION("Tegra30 MC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
--
1.7.5.4
Add Tegra MC(Memory Controller) nodes for tegra30.dtsi.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
arch/arm/boot/dts/tegra30.dtsi | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 9d650fb..167ccbc 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -229,4 +229,13 @@
compatible = "nvidia,tegra30-ahb";
reg = <0x6000c004 0x14c>; /* AHB Arbitration + Gizmo Controller */
};
+
+ mc {
+ compatible = "nvidia,tegra30-mc";
+ reg = <0x7000f000 0x010
+ 0x7000f03c 0x1b4
+ 0x7000f200 0x028
+ 0x7000f284 0x17c>;
+ interrupts = <0 77 0x04>;
+ };
};
--
1.7.5.4
On 05/10/2012 01:42 AM, Hiroshi DOYU wrote:
> Tegra Memory Controller(MC) driver for Tegra20
> Added to support MC General interrupts, mainly for IOMMU(GART).
Greg, you appear to have been commiting all of drivers/memory. I assume
you'll take patches 1 and 3 in this series, and I will take 2 and 4
through the Tegra tree? I can take them all through the Tegra tree if
you want. Taking the .dts patches through your tree might cause
conflicts in 3.6, since I anticipate some DT-wide cleanup in 3.6.
Hiroshi, one question below (same for patch 3)
> diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
> @@ -20,6 +20,8 @@ config ARCH_TEGRA_2x_SOC
> select PL310_ERRATA_727915 if CACHE_L2X0
> select PL310_ERRATA_769419 if CACHE_L2X0
> select CPU_FREQ_TABLE if CPU_FREQ
> + select MEMORY
> + select TEGRA20_MC
Does ARCH_TEGRA_2x_SOC /have/ to select these?
I'd be inclined to drop the change to mach-tegra/Kconfig. As rationale,
the code works fine without the driver right now. You'd need to make
config TEGRA*_MC user-visible/selectable though.
You could replace this change with a patch to tegra_defconfig which
enables MEMORY and TEGRA*_MC, or perhaps make config TEGRA20_MC default y.
What are people's thoughts here?
Aside from this, the series looks fine to me.
On Thu, May 10, 2012 at 11:23:55AM -0600, Stephen Warren wrote:
> On 05/10/2012 01:42 AM, Hiroshi DOYU wrote:
> > Tegra Memory Controller(MC) driver for Tegra20
> > Added to support MC General interrupts, mainly for IOMMU(GART).
>
> Greg, you appear to have been commiting all of drivers/memory. I assume
> you'll take patches 1 and 3 in this series, and I will take 2 and 4
> through the Tegra tree? I can take them all through the Tegra tree if
> you want.
I think you will get a conflict if you take the memory ones in your
tree, so I will take those two, thanks.
greg k-h
On Thu, May 10, 2012 at 10:42:32AM +0300, Hiroshi DOYU wrote:
> Tegra Memory Controller(MC) driver for Tegra30
> Added to support MC General interrupts, mainly for IOMMU(SMMU).
I'll apply this, but:
> +static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs)
> +{
> + if (offs < 0x10)
> + return readl(mc->regs[0] + offs);
> + BUG_ON(offs < 0x3c);
> + if (offs < 0x1f0)
> + return readl(mc->regs[1] + offs - 0x3c);
> + BUG_ON(offs < 0x200);
> + if (offs < 0x228)
> + return readl(mc->regs[2] + offs - 0x200);
> + BUG_ON(offs < 0x284);
> + if (offs < 0x400)
> + return readl(mc->regs[3] + offs - 0x284);
> + BUG();
> +}
That's a lot of BUG* calls. Same thing with the 1/4 patch in this
series.
We really should not have a BUG call in any driver, as you just stopped
the whole system. I can understand this being there for debugging when
you create the code originally, but as these are things no one should
ever be able to hit now, you should remove them, right?
Care to write a follow-on patch removing all of these BUG_ON and BUG
calls in this and the drivers/memory/tegra20-mc.c driver?
thanks,
greg k-h
Hi Greg,
From: Greg Kroah-Hartman <[email protected]>
Subject: Re: [PATCH 3/4] ARM: tegra30: Add Tegra Memory Controller(MC) driver
Date: Thu, 10 May 2012 23:46:04 +0200
Message-ID: <[email protected]>
> On Thu, May 10, 2012 at 10:42:32AM +0300, Hiroshi DOYU wrote:
> > Tegra Memory Controller(MC) driver for Tegra30
> > Added to support MC General interrupts, mainly for IOMMU(SMMU).
>
> I'll apply this, but:
Thanks.
> > +static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs)
> > +{
> > + if (offs < 0x10)
> > + return readl(mc->regs[0] + offs);
> > + BUG_ON(offs < 0x3c);
> > + if (offs < 0x1f0)
> > + return readl(mc->regs[1] + offs - 0x3c);
> > + BUG_ON(offs < 0x200);
> > + if (offs < 0x228)
> > + return readl(mc->regs[2] + offs - 0x200);
> > + BUG_ON(offs < 0x284);
> > + if (offs < 0x400)
> > + return readl(mc->regs[3] + offs - 0x284);
> > + BUG();
> > +}
>
> That's a lot of BUG* calls. Same thing with the 1/4 patch in this
> series.
>
> We really should not have a BUG call in any driver, as you just stopped
> the whole system. I can understand this being there for debugging when
> you create the code originally, but as these are things no one should
> ever be able to hit now, you should remove them, right?
>
> Care to write a follow-on patch removing all of these BUG_ON and BUG
> calls in this and the drivers/memory/tegra20-mc.c driver?
Ok, they are replying to this email.
Accessing interleaved MC register offsets/ranges are verified. BUG*()s
in accessors can be removed.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
drivers/memory/tegra20-mc.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c
index c0bfffa..6832604 100644
--- a/drivers/memory/tegra20-mc.c
+++ b/drivers/memory/tegra20-mc.c
@@ -55,10 +55,8 @@ static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs)
{
if (offs < 0x24)
return readl(mc->regs[0] + offs);
- BUG_ON(offs < 0x3c);
if (offs < 0x400)
return readl(mc->regs[1] + offs - 0x3c);
- BUG();
}
static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs)
@@ -67,12 +65,10 @@ static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs)
writel(val, mc->regs[0] + offs);
return;
}
- BUG_ON(offs < 0x3c);
if (offs < 0x400) {
writel(val, mc->regs[1] + offs - 0x3c);
return;
}
- BUG();
}
static const char * const tegra20_mc_client[] = {
--
1.7.5.4
Accessing interleaved MC register offsets/ranges are verified. BUG*()s
in accessors can be removed.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
drivers/memory/tegra30-mc.c | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
index c982125..4905cd8 100644
--- a/drivers/memory/tegra30-mc.c
+++ b/drivers/memory/tegra30-mc.c
@@ -93,16 +93,12 @@ static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs)
{
if (offs < 0x10)
return readl(mc->regs[0] + offs);
- BUG_ON(offs < 0x3c);
if (offs < 0x1f0)
return readl(mc->regs[1] + offs - 0x3c);
- BUG_ON(offs < 0x200);
if (offs < 0x228)
return readl(mc->regs[2] + offs - 0x200);
- BUG_ON(offs < 0x284);
if (offs < 0x400)
return readl(mc->regs[3] + offs - 0x284);
- BUG();
}
static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs)
@@ -111,22 +107,18 @@ static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs)
writel(val, mc->regs[0] + offs);
return;
}
- BUG_ON(offs < 0x3c);
if (offs < 0x1f0) {
writel(val, mc->regs[1] + offs - 0x3c);
return;
}
- BUG_ON(offs < 0x200);
if (offs < 0x228) {
writel(val, mc->regs[2] + offs - 0x200);
return;
}
- BUG_ON(offs < 0x284);
if (offs < 0x400) {
writel(val, mc->regs[3] + offs - 0x284);
return;
}
- BUG();
}
static const char * const tegra30_mc_client[] = {
--
1.7.5.4
Hi Greg, Stephen,
On Thu, 10 May 2012 19:23:55 +0200
Stephen Warren <[email protected]> wrote:
> On 05/10/2012 01:42 AM, Hiroshi DOYU wrote:
> > Tegra Memory Controller(MC) driver for Tegra20
> > Added to support MC General interrupts, mainly for IOMMU(GART).
>
> Greg, you appear to have been commiting all of drivers/memory. I assume
> you'll take patches 1 and 3 in this series, and I will take 2 and 4
> through the Tegra tree? I can take them all through the Tegra tree if
> you want. Taking the .dts patches through your tree might cause
> conflicts in 3.6, since I anticipate some DT-wide cleanup in 3.6.
>
> Hiroshi, one question below (same for patch 3)
>
> > diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
>
> > @@ -20,6 +20,8 @@ config ARCH_TEGRA_2x_SOC
> > select PL310_ERRATA_727915 if CACHE_L2X0
> > select PL310_ERRATA_769419 if CACHE_L2X0
> > select CPU_FREQ_TABLE if CPU_FREQ
> > + select MEMORY
> > + select TEGRA20_MC
>
> Does ARCH_TEGRA_2x_SOC /have/ to select these?
>
> I'd be inclined to drop the change to mach-tegra/Kconfig. As rationale,
> the code works fine without the driver right now. You'd need to make
> config TEGRA*_MC user-visible/selectable though.
>
> You could replace this change with a patch to tegra_defconfig which
> enables MEMORY and TEGRA*_MC, or perhaps make config TEGRA20_MC default y.
I'm sending the fixup patches, following this mail, since Greg has
already put the original patches in queue. I think that the following
fixup patches could be squashed into the original ones. The fixup
patches are:
[PATCH 1/3] ARM: tegra20: Make MC optional in Kconfig
[PATCH 2/3] ARM: tegra30: Make MC optional in Kconfig
[PATCH 3/3] ARM: tegra: Make TEGRA{20,30}_MC selectable in defconfig
Let me know if it's better to resend the complete patches again.
For bare minimal system.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
arch/arm/mach-tegra/Kconfig | 2 --
drivers/memory/Kconfig | 8 +++++++-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 16fe065..8b6b181 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -20,8 +20,6 @@ config ARCH_TEGRA_2x_SOC
select PL310_ERRATA_727915 if CACHE_L2X0
select PL310_ERRATA_769419 if CACHE_L2X0
select CPU_FREQ_TABLE if CPU_FREQ
- select MEMORY
- select TEGRA20_MC
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 42e6d66..efc6b36 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -21,8 +21,14 @@ config TI_EMIF
temperature changes
config TEGRA20_MC
- bool
+ bool "Tegra20 Memory Controller(MC) driver"
+ default y
depends on ARCH_TEGRA_2x_SOC
+ help
+ This driver is for the Memory Controller(MC) module available
+ in Tegra20 SoCs, mainly for a address translation fault
+ analysis, especially for IOMMU/GART(Graphics Address
+ Relocation Table) module.
config TEGRA30_MC
bool
--
1.7.5.4
For bare minimal system.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
arch/arm/mach-tegra/Kconfig | 2 --
drivers/memory/Kconfig | 8 +++++++-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 8b6b181..6a113a9 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -41,8 +41,6 @@ config ARCH_TEGRA_3x_SOC
select ARM_ERRATA_764369
select PL310_ERRATA_769419 if CACHE_L2X0
select CPU_FREQ_TABLE if CPU_FREQ
- select MEMORY
- select TEGRA30_MC
help
Support for NVIDIA Tegra T30 processor family, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index efc6b36..067f311 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -31,7 +31,13 @@ config TEGRA20_MC
Relocation Table) module.
config TEGRA30_MC
- bool
+ bool "Tegra30 Memory Controller(MC) driver"
+ default y
depends on ARCH_TEGRA_3x_SOC
+ help
+ This driver is for the Memory Controller(MC) module available
+ in Tegra30 SoCs, mainly for a address translation fault
+ analysis, especially for IOMMU/SMMU(System Memory Management
+ Unit) module.
endif
--
1.7.5.4
CONFIG_TEGRA{20,30}_MC depends on CONFIG_MEMORY.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
arch/arm/configs/tegra_defconfig | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 7a90abb..639778d 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -149,6 +149,7 @@ CONFIG_KEYBOARD_NVEC=y
CONFIG_SERIO_NVEC_PS2=y
CONFIG_TEGRA_IOMMU_GART=y
CONFIG_TEGRA_IOMMU_SMMU=y
+CONFIG_MEMORY=y
CONFIG_IIO=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
--
1.7.5.4
Accessing interleaved MC register offsets/ranges are verified. BUG*()s
in accessors can be removed.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
drivers/memory/tegra30-mc.c | 20 ++++++++------------
1 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
index c982125..ec9fc78 100644
--- a/drivers/memory/tegra30-mc.c
+++ b/drivers/memory/tegra30-mc.c
@@ -91,18 +91,18 @@ struct tegra30_mc {
static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs)
{
+ u32 val = 0;
+
if (offs < 0x10)
- return readl(mc->regs[0] + offs);
- BUG_ON(offs < 0x3c);
+ val = readl(mc->regs[0] + offs);
if (offs < 0x1f0)
- return readl(mc->regs[1] + offs - 0x3c);
- BUG_ON(offs < 0x200);
+ val = readl(mc->regs[1] + offs - 0x3c);
if (offs < 0x228)
- return readl(mc->regs[2] + offs - 0x200);
- BUG_ON(offs < 0x284);
+ val = readl(mc->regs[2] + offs - 0x200);
if (offs < 0x400)
- return readl(mc->regs[3] + offs - 0x284);
- BUG();
+ val = readl(mc->regs[3] + offs - 0x284);
+
+ return val;
}
static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs)
@@ -111,22 +111,18 @@ static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs)
writel(val, mc->regs[0] + offs);
return;
}
- BUG_ON(offs < 0x3c);
if (offs < 0x1f0) {
writel(val, mc->regs[1] + offs - 0x3c);
return;
}
- BUG_ON(offs < 0x200);
if (offs < 0x228) {
writel(val, mc->regs[2] + offs - 0x200);
return;
}
- BUG_ON(offs < 0x284);
if (offs < 0x400) {
writel(val, mc->regs[3] + offs - 0x284);
return;
}
- BUG();
}
static const char * const tegra30_mc_client[] = {
--
1.7.5.4
Accessing interleaved MC register offsets/ranges are verified. BUG*()s
in accessors can be removed.
Signed-off-by: Hiroshi DOYU <[email protected]>
---
drivers/memory/tegra20-mc.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c
index c0bfffa..2a437e9 100644
--- a/drivers/memory/tegra20-mc.c
+++ b/drivers/memory/tegra20-mc.c
@@ -53,12 +53,14 @@ struct tegra20_mc {
static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs)
{
+ u32 val = 0;
+
if (offs < 0x24)
- return readl(mc->regs[0] + offs);
- BUG_ON(offs < 0x3c);
+ val = readl(mc->regs[0] + offs);
if (offs < 0x400)
- return readl(mc->regs[1] + offs - 0x3c);
- BUG();
+ val = readl(mc->regs[1] + offs - 0x3c);
+
+ return val;
}
static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs)
@@ -67,12 +69,10 @@ static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs)
writel(val, mc->regs[0] + offs);
return;
}
- BUG_ON(offs < 0x3c);
if (offs < 0x400) {
writel(val, mc->regs[1] + offs - 0x3c);
return;
}
- BUG();
}
static const char * const tegra20_mc_client[] = {
--
1.7.5.4
On 05/11/2012 12:56 AM, Hiroshi DOYU wrote:
> For bare minimal system.
>
> Signed-off-by: Hiroshi DOYU <[email protected]>
Patches 1 and 2,
Acked-by: Stephen Warren <[email protected]>
I'll take patch 3 through the Tegra tree along with the .dts changes.
On Fri, May 11, 2012 at 11:54:29AM -0600, Stephen Warren wrote:
> On 05/11/2012 12:56 AM, Hiroshi DOYU wrote:
> > For bare minimal system.
> >
> > Signed-off-by: Hiroshi DOYU <[email protected]>
>
> Patches 1 and 2,
>
> Acked-by: Stephen Warren <[email protected]>
Thanks, now applied.
greg k-h
Hi,
Tiny drive-by nit pick.
On Thu, May 10, 2012 at 12:42 AM, Hiroshi DOYU <[email protected]> wrote:
> Add Tegra MC(Memory Controller) nodes for tegra20.dtsi.
>
> Signed-off-by: Hiroshi DOYU <[email protected]>
> ---
> ?arch/arm/boot/dts/tegra20.dtsi | ? ?7 +++++++
> ?1 files changed, 7 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
> index 24129fb..548b42e 100644
> --- a/arch/arm/boot/dts/tegra20.dtsi
> +++ b/arch/arm/boot/dts/tegra20.dtsi
> @@ -211,5 +211,12 @@
> ? ? ? ? ? ? ? ?compatible = "nvidia,tegra20-ahb";
> ? ? ? ? ? ? ? ?reg = <0x6000c004 0x10c>; /* AHB Arbitration + Gizmo Controller */
> ? ? ? ?};
> +
> + ? ? ? mc {
It's common to use a more plain english name here, so
"memory-controller" would be a good name.
-Olof
Hi Olof,
On Wed, 16 May 2012 08:35:02 +0200
Olof Johansson <[email protected]> wrote:
> Hi,
>
> Tiny drive-by nit pick.
>
> On Thu, May 10, 2012 at 12:42 AM, Hiroshi DOYU <[email protected]> wrote:
> > Add Tegra MC(Memory Controller) nodes for tegra20.dtsi.
> >
> > Signed-off-by: Hiroshi DOYU <[email protected]>
> > ---
> > ?arch/arm/boot/dts/tegra20.dtsi | ? ?7 +++++++
> > ?1 files changed, 7 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
> > index 24129fb..548b42e 100644
> > --- a/arch/arm/boot/dts/tegra20.dtsi
> > +++ b/arch/arm/boot/dts/tegra20.dtsi
> > @@ -211,5 +211,12 @@
> > ? ? ? ? ? ? ? ?compatible = "nvidia,tegra20-ahb";
> > ? ? ? ? ? ? ? ?reg = <0x6000c004 0x10c>; /* AHB Arbitration + Gizmo Controller */
> > ? ? ? ?};
> > +
> > + ? ? ? mc {
>
> It's common to use a more plain english name here, so
> "memory-controller" would be a good name.
Agree. Seems to be common as below. Fix patches follows, which can be squashed if possible.
$% grep memory-controller arch/arm/boot/dts/*
arch/arm/boot/dts/prima2-cb.dts: memory-controller@90000000 {
arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts: memory-controller@2b0a0000 {
arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts: memory-controller@7ffd0000 {
arch/arm/boot/dts/vexpress-v2p-ca5s.dts: memory-controller@2a150000 {
arch/arm/boot/dts/vexpress-v2p-ca5s.dts: memory-controller@2a190000 {
arch/arm/boot/dts/vexpress-v2p-ca9.dts: memory-controller@100e0000 {
arch/arm/boot/dts/vexpress-v2p-ca9.dts: memory-controller@100e1000 {