Merge tag 'tegra-for-5.5-memory-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/drivers

memory: tegra: Changes for v5.5-rc1

This contains a couple of fixes and adds support for EMC frequency
scaling on Tegra30.

* tag 'tegra-for-5.5-memory-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  memory: tegra: Consolidate registers definition into common header
  memory: tegra: Ensure timing control debug features are disabled
  memory: tegra: Introduce Tegra30 EMC driver
  memory: tegra: Do not handle error from wait_for_completion_timeout()
  memory: tegra: Increase handshake timeout on Tegra20
  memory: tegra: Print a brief info message about EMC timings
  memory: tegra: Pre-configure debug register on Tegra20
  memory: tegra: Include io.h instead of iopoll.h
  memory: tegra: Adapt for Tegra20 clock driver changes
  memory: tegra: Don't set EMC rate to maximum on probe for Tegra20
  memory: tegra: Add gr2d and gr3d to DRM IOMMU group
  memory: tegra: Set DMA mask based on supported address bits
  clk: tegra: Add Tegra20/30 EMC clock implementation

Link: https://lore.kernel.org/r/20191111143836.4027200-1-thierry.reding@gmail.com
Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson
2019-11-11 13:13:22 -08:00
16 changed files with 1781 additions and 204 deletions

View File

@@ -17,6 +17,16 @@ config TEGRA20_EMC
This driver is required to change memory timings / clock rate for
external memory.
config TEGRA30_EMC
bool "NVIDIA Tegra30 External Memory Controller driver"
default y
depends on TEGRA_MC && ARCH_TEGRA_3x_SOC
help
This driver is for the External Memory Controller (EMC) found on
Tegra30 chips. The EMC controls the external DRAM on the board.
This driver is required to change memory timings / clock rate for
external memory.
config TEGRA124_EMC
bool "NVIDIA Tegra124 External Memory Controller driver"
default y

View File

@@ -11,5 +11,6 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
obj-$(CONFIG_TEGRA20_EMC) += tegra20-emc.o
obj-$(CONFIG_TEGRA30_EMC) += tegra30-emc.o
obj-$(CONFIG_TEGRA124_EMC) += tegra124-emc.o
obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o

View File

@@ -5,6 +5,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -18,39 +19,6 @@
#include "mc.h"
#define MC_INTSTATUS 0x000
#define MC_INTMASK 0x004
#define MC_ERR_STATUS 0x08
#define MC_ERR_STATUS_TYPE_SHIFT 28
#define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (6 << MC_ERR_STATUS_TYPE_SHIFT)
#define MC_ERR_STATUS_TYPE_MASK (0x7 << MC_ERR_STATUS_TYPE_SHIFT)
#define MC_ERR_STATUS_READABLE (1 << 27)
#define MC_ERR_STATUS_WRITABLE (1 << 26)
#define MC_ERR_STATUS_NONSECURE (1 << 25)
#define MC_ERR_STATUS_ADR_HI_SHIFT 20
#define MC_ERR_STATUS_ADR_HI_MASK 0x3
#define MC_ERR_STATUS_SECURITY (1 << 17)
#define MC_ERR_STATUS_RW (1 << 16)
#define MC_ERR_ADR 0x0c
#define MC_GART_ERROR_REQ 0x30
#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
#define MC_SECURITY_VIOLATION_STATUS 0x74
#define MC_EMEM_ARB_CFG 0x90
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) (((x) & 0x1ff) << 0)
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
#define MC_EMEM_ARB_MISC0 0xd8
#define MC_EMEM_ADR_CFG 0x54
#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
#define MC_TIMING_CONTROL 0xfc
#define MC_TIMING_UPDATE BIT(0)
static const struct of_device_id tegra_mc_of_match[] = {
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
{ .compatible = "nvidia,tegra20-mc-gart", .data = &tegra20_mc_soc },
@@ -307,7 +275,7 @@ static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
return 0;
}
void tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate)
int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate)
{
unsigned int i;
struct tegra_mc_timing *timing = NULL;
@@ -322,11 +290,13 @@ void tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate)
if (!timing) {
dev_err(mc->dev, "no memory timing registered for rate %lu\n",
rate);
return;
return -EINVAL;
}
for (i = 0; i < mc->soc->num_emem_regs; ++i)
mc_writel(mc, timing->emem_data[i], mc->soc->emem_regs[i]);
return 0;
}
unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc)
@@ -626,6 +596,7 @@ static int tegra_mc_probe(struct platform_device *pdev)
struct resource *res;
struct tegra_mc *mc;
void *isr;
u64 mask;
int err;
mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
@@ -637,6 +608,14 @@ static int tegra_mc_probe(struct platform_device *pdev)
mc->soc = of_device_get_match_data(&pdev->dev);
mc->dev = &pdev->dev;
mask = DMA_BIT_MASK(mc->soc->num_address_bits);
err = dma_coerce_mask_and_coherent(&pdev->dev, mask);
if (err < 0) {
dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
return err;
}
/* length of MC tick in nanoseconds */
mc->tick = 30;
@@ -658,6 +637,9 @@ static int tegra_mc_probe(struct platform_device *pdev)
} else
#endif
{
/* ensure that debug features are disabled */
mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG);
err = tegra_mc_setup_latency_allowance(mc);
if (err < 0) {
dev_err(&pdev->dev,

View File

@@ -6,20 +6,76 @@
#ifndef MEMORY_TEGRA_MC_H
#define MEMORY_TEGRA_MC_H
#include <linux/bits.h>
#include <linux/io.h>
#include <linux/types.h>
#include <soc/tegra/mc.h>
#define MC_INT_DECERR_MTS (1 << 16)
#define MC_INT_SECERR_SEC (1 << 13)
#define MC_INT_DECERR_VPR (1 << 12)
#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11)
#define MC_INT_INVALID_SMMU_PAGE (1 << 10)
#define MC_INT_ARBITRATION_EMEM (1 << 9)
#define MC_INT_SECURITY_VIOLATION (1 << 8)
#define MC_INT_INVALID_GART_PAGE (1 << 7)
#define MC_INT_DECERR_EMEM (1 << 6)
#define MC_INTSTATUS 0x00
#define MC_INTMASK 0x04
#define MC_ERR_STATUS 0x08
#define MC_ERR_ADR 0x0c
#define MC_GART_ERROR_REQ 0x30
#define MC_EMEM_ADR_CFG 0x54
#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
#define MC_SECURITY_VIOLATION_STATUS 0x74
#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_RING1_THROTTLE 0xe0
#define MC_EMEM_ARB_OVERRIDE 0xe8
#define MC_TIMING_CONTROL_DBG 0xf8
#define MC_TIMING_CONTROL 0xfc
#define MC_INT_DECERR_MTS BIT(16)
#define MC_INT_SECERR_SEC BIT(13)
#define MC_INT_DECERR_VPR BIT(12)
#define MC_INT_INVALID_APB_ASID_UPDATE BIT(11)
#define MC_INT_INVALID_SMMU_PAGE BIT(10)
#define MC_INT_ARBITRATION_EMEM BIT(9)
#define MC_INT_SECURITY_VIOLATION BIT(8)
#define MC_INT_INVALID_GART_PAGE BIT(7)
#define MC_INT_DECERR_EMEM BIT(6)
#define MC_ERR_STATUS_TYPE_SHIFT 28
#define MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (0x6 << 28)
#define MC_ERR_STATUS_TYPE_MASK (0x7 << 28)
#define MC_ERR_STATUS_READABLE BIT(27)
#define MC_ERR_STATUS_WRITABLE BIT(26)
#define MC_ERR_STATUS_NONSECURE BIT(25)
#define MC_ERR_STATUS_ADR_HI_SHIFT 20
#define MC_ERR_STATUS_ADR_HI_MASK 0x3
#define MC_ERR_STATUS_SECURITY BIT(17)
#define MC_ERR_STATUS_RW BIT(16)
#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) ((x) & 0x1ff)
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
#define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK 0x1ff
#define MC_EMEM_ARB_OUTSTANDING_REQ_HOLDOFF_OVERRIDE BIT(30)
#define MC_EMEM_ARB_OUTSTANDING_REQ_LIMIT_ENABLE BIT(31)
#define MC_EMEM_ARB_OVERRIDE_EACK_MASK 0x3
#define MC_TIMING_UPDATE BIT(0)
static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset)
{

View File

@@ -909,16 +909,18 @@ static const struct tegra_smmu_swgroup tegra114_swgroups[] = {
{ .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 },
};
static const unsigned int tegra114_group_display[] = {
static const unsigned int tegra114_group_drm[] = {
TEGRA_SWGROUP_DC,
TEGRA_SWGROUP_DCB,
TEGRA_SWGROUP_G2,
TEGRA_SWGROUP_NV,
};
static const struct tegra_smmu_group_soc tegra114_groups[] = {
{
.name = "display",
.swgroups = tegra114_group_display,
.num_swgroups = ARRAY_SIZE(tegra114_group_display),
.name = "drm",
.swgroups = tegra114_group_drm,
.num_swgroups = ARRAY_SIZE(tegra114_group_drm),
},
};

View File

@@ -10,26 +10,6 @@
#include "mc.h"
#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_RING1_THROTTLE 0xe0
static const struct tegra_mc_client tegra124_mc_clients[] = {
{
.id = 0x00,
@@ -974,16 +954,18 @@ static const struct tegra_smmu_swgroup tegra124_swgroups[] = {
{ .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 },
};
static const unsigned int tegra124_group_display[] = {
static const unsigned int tegra124_group_drm[] = {
TEGRA_SWGROUP_DC,
TEGRA_SWGROUP_DCB,
TEGRA_SWGROUP_GPU,
TEGRA_SWGROUP_VIC,
};
static const struct tegra_smmu_group_soc tegra124_groups[] = {
{
.name = "display",
.swgroups = tegra124_group_display,
.num_swgroups = ARRAY_SIZE(tegra124_group_display),
.name = "drm",
.swgroups = tegra124_group_drm,
.num_swgroups = ARRAY_SIZE(tegra124_group_drm),
},
};

View File

@@ -6,10 +6,11 @@
*/
#include <linux/clk.h>
#include <linux/clk/tegra.h>
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -21,6 +22,7 @@
#define EMC_INTSTATUS 0x000
#define EMC_INTMASK 0x004
#define EMC_DBG 0x008
#define EMC_TIMING_CONTROL 0x028
#define EMC_RC 0x02c
#define EMC_RFC 0x030
@@ -79,6 +81,12 @@
#define EMC_REFRESH_OVERFLOW_INT BIT(3)
#define EMC_CLKCHANGE_COMPLETE_INT BIT(4)
#define EMC_DBG_READ_MUX_ASSEMBLY BIT(0)
#define EMC_DBG_WRITE_MUX_ACTIVE BIT(1)
#define EMC_DBG_FORCE_UPDATE BIT(2)
#define EMC_DBG_READ_DQM_CTRL BIT(9)
#define EMC_DBG_CFG_PRIORITY BIT(24)
static const u16 emc_timing_registers[] = {
EMC_RC,
EMC_RFC,
@@ -137,9 +145,6 @@ struct tegra_emc {
struct device *dev;
struct completion clk_handshake_complete;
struct notifier_block clk_nb;
struct clk *backup_clk;
struct clk *emc_mux;
struct clk *pll_m;
struct clk *clk;
void __iomem *regs;
@@ -219,7 +224,7 @@ static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate)
static int emc_complete_timing_change(struct tegra_emc *emc, bool flush)
{
long timeout;
unsigned long timeout;
dev_dbg(emc->dev, "%s: flush %d\n", __func__, flush);
@@ -231,14 +236,10 @@ static int emc_complete_timing_change(struct tegra_emc *emc, bool flush)
}
timeout = wait_for_completion_timeout(&emc->clk_handshake_complete,
usecs_to_jiffies(100));
msecs_to_jiffies(100));
if (timeout == 0) {
dev_err(emc->dev, "EMC-CAR handshake failed\n");
return -EIO;
} else if (timeout < 0) {
dev_err(emc->dev, "failed to wait for EMC-CAR handshake: %ld\n",
timeout);
return timeout;
}
return 0;
@@ -363,6 +364,13 @@ static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
sort(emc->timings, emc->num_timings, sizeof(*timing), cmp_timings,
NULL);
dev_info(emc->dev,
"got %u timings for RAM code %u (min %luMHz max %luMHz)\n",
emc->num_timings,
tegra_read_ram_code(),
emc->timings[0].rate / 1000000,
emc->timings[emc->num_timings - 1].rate / 1000000);
return 0;
}
@@ -398,7 +406,7 @@ tegra_emc_find_node_by_ram_code(struct device *dev)
static int emc_setup_hw(struct tegra_emc *emc)
{
u32 intmask = EMC_REFRESH_OVERFLOW_INT | EMC_CLKCHANGE_COMPLETE_INT;
u32 emc_cfg;
u32 emc_cfg, emc_dbg;
emc_cfg = readl_relaxed(emc->regs + EMC_CFG_2);
@@ -421,42 +429,53 @@ static int emc_setup_hw(struct tegra_emc *emc)
writel_relaxed(intmask, emc->regs + EMC_INTMASK);
writel_relaxed(intmask, emc->regs + EMC_INTSTATUS);
/* ensure that unwanted debug features are disabled */
emc_dbg = readl_relaxed(emc->regs + EMC_DBG);
emc_dbg |= EMC_DBG_CFG_PRIORITY;
emc_dbg &= ~EMC_DBG_READ_MUX_ASSEMBLY;
emc_dbg &= ~EMC_DBG_WRITE_MUX_ACTIVE;
emc_dbg &= ~EMC_DBG_FORCE_UPDATE;
writel_relaxed(emc_dbg, emc->regs + EMC_DBG);
return 0;
}
static int emc_init(struct tegra_emc *emc, unsigned long rate)
static long emc_round_rate(unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
void *arg)
{
int err;
struct emc_timing *timing = NULL;
struct tegra_emc *emc = arg;
unsigned int i;
err = clk_set_parent(emc->emc_mux, emc->backup_clk);
if (err) {
dev_err(emc->dev,
"failed to reparent to backup source: %d\n", err);
return err;
min_rate = min(min_rate, emc->timings[emc->num_timings - 1].rate);
for (i = 0; i < emc->num_timings; i++) {
if (emc->timings[i].rate < rate && i != emc->num_timings - 1)
continue;
if (emc->timings[i].rate > max_rate) {
i = max(i, 1u) - 1;
if (emc->timings[i].rate < min_rate)
break;
}
if (emc->timings[i].rate < min_rate)
continue;
timing = &emc->timings[i];
break;
}
err = clk_set_rate(emc->pll_m, rate);
if (err) {
dev_err(emc->dev,
"failed to change pll_m rate: %d\n", err);
return err;
if (!timing) {
dev_err(emc->dev, "no timing for rate %lu min %lu max %lu\n",
rate, min_rate, max_rate);
return -EINVAL;
}
err = clk_set_parent(emc->emc_mux, emc->pll_m);
if (err) {
dev_err(emc->dev,
"failed to reparent to pll_m: %d\n", err);
return err;
}
err = clk_set_rate(emc->clk, rate);
if (err) {
dev_err(emc->dev,
"failed to change emc rate: %d\n", err);
return err;
}
return 0;
return timing->rate;
}
static int tegra_emc_probe(struct platform_device *pdev)
@@ -515,57 +534,26 @@ static int tegra_emc_probe(struct platform_device *pdev)
return err;
}
tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
emc->clk = devm_clk_get(&pdev->dev, "emc");
if (IS_ERR(emc->clk)) {
err = PTR_ERR(emc->clk);
dev_err(&pdev->dev, "failed to get emc clock: %d\n", err);
return err;
}
emc->pll_m = clk_get_sys(NULL, "pll_m");
if (IS_ERR(emc->pll_m)) {
err = PTR_ERR(emc->pll_m);
dev_err(&pdev->dev, "failed to get pll_m clock: %d\n", err);
return err;
}
emc->backup_clk = clk_get_sys(NULL, "pll_p");
if (IS_ERR(emc->backup_clk)) {
err = PTR_ERR(emc->backup_clk);
dev_err(&pdev->dev, "failed to get pll_p clock: %d\n", err);
goto put_pll_m;
}
emc->emc_mux = clk_get_parent(emc->clk);
if (IS_ERR(emc->emc_mux)) {
err = PTR_ERR(emc->emc_mux);
dev_err(&pdev->dev, "failed to get emc_mux clock: %d\n", err);
goto put_backup;
goto unset_cb;
}
err = clk_notifier_register(emc->clk, &emc->clk_nb);
if (err) {
dev_err(&pdev->dev, "failed to register clk notifier: %d\n",
err);
goto put_backup;
}
/* set DRAM clock rate to maximum */
err = emc_init(emc, emc->timings[emc->num_timings - 1].rate);
if (err) {
dev_err(&pdev->dev, "failed to initialize EMC clock rate: %d\n",
err);
goto unreg_notifier;
goto unset_cb;
}
return 0;
unreg_notifier:
clk_notifier_unregister(emc->clk, &emc->clk_nb);
put_backup:
clk_put(emc->backup_clk);
put_pll_m:
clk_put(emc->pll_m);
unset_cb:
tegra20_clk_set_emc_round_callback(NULL, NULL);
return err;
}

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,27 @@
#include "mc.h"
static const unsigned long tegra30_mc_emem_regs[] = {
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_RING1_THROTTLE,
};
static const struct tegra_mc_client tegra30_mc_clients[] = {
{
.id = 0x00,
@@ -931,16 +952,19 @@ static const struct tegra_smmu_swgroup tegra30_swgroups[] = {
{ .name = "isp", .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 },
};
static const unsigned int tegra30_group_display[] = {
static const unsigned int tegra30_group_drm[] = {
TEGRA_SWGROUP_DC,
TEGRA_SWGROUP_DCB,
TEGRA_SWGROUP_G2,
TEGRA_SWGROUP_NV,
TEGRA_SWGROUP_NV2,
};
static const struct tegra_smmu_group_soc tegra30_groups[] = {
{
.name = "display",
.swgroups = tegra30_group_display,
.num_swgroups = ARRAY_SIZE(tegra30_group_display),
.name = "drm",
.swgroups = tegra30_group_drm,
.num_swgroups = ARRAY_SIZE(tegra30_group_drm),
},
};
@@ -994,6 +1018,8 @@ const struct tegra_mc_soc tegra30_mc_soc = {
.atom_size = 16,
.client_id_mask = 0x7f,
.smmu = &tegra30_smmu_soc,
.emem_regs = tegra30_mc_emem_regs,
.num_emem_regs = ARRAY_SIZE(tegra30_mc_emem_regs),
.intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
MC_INT_DECERR_EMEM,
.reset_ops = &tegra_mc_reset_ops_common,