1
0
Fork 0

memory: tegra: Add Tegra186 support

The memory controller found on Tegra186 is different in some respects to
its predecessors. Most notably it no longer implements an SMMU, but does
assign ARM SMMU stream IDs for each memory client instead.

Provide a driver that programs these registers so that memory clients
can translate addresses via the ARM SMMU.

Signed-off-by: Thierry Reding <treding@nvidia.com>
hifive-unleashed-5.1
Thierry Reding 2017-12-13 12:58:21 +01:00
parent fc17a91fd1
commit 02b0cc52c0
2 changed files with 601 additions and 0 deletions

View File

@ -10,3 +10,4 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
obj-$(CONFIG_TEGRA124_EMC) += tegra124-emc.o
obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o

View File

@ -0,0 +1,600 @@
/*
* Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <dt-bindings/memory/tegra186-mc.h>
struct tegra_mc {
struct device *dev;
void __iomem *regs;
};
struct tegra_mc_client {
const char *name;
unsigned int sid;
struct {
unsigned int override;
unsigned int security;
} regs;
};
static const struct tegra_mc_client tegra186_mc_clients[] = {
{
.name = "ptcr",
.sid = TEGRA186_SID_PASSTHROUGH,
.regs = {
.override = 0x000,
.security = 0x004,
},
}, {
.name = "afir",
.sid = TEGRA186_SID_AFI,
.regs = {
.override = 0x070,
.security = 0x074,
},
}, {
.name = "hdar",
.sid = TEGRA186_SID_HDA,
.regs = {
.override = 0x0a8,
.security = 0x0ac,
},
}, {
.name = "host1xdmar",
.sid = TEGRA186_SID_HOST1X,
.regs = {
.override = 0x0b0,
.security = 0x0b4,
},
}, {
.name = "nvencsrd",
.sid = TEGRA186_SID_NVENC,
.regs = {
.override = 0x0e0,
.security = 0x0e4,
},
}, {
.name = "satar",
.sid = TEGRA186_SID_SATA,
.regs = {
.override = 0x0f8,
.security = 0x0fc,
},
}, {
.name = "mpcorer",
.sid = TEGRA186_SID_PASSTHROUGH,
.regs = {
.override = 0x138,
.security = 0x13c,
},
}, {
.name = "nvencswr",
.sid = TEGRA186_SID_NVENC,
.regs = {
.override = 0x158,
.security = 0x15c,
},
}, {
.name = "afiw",
.sid = TEGRA186_SID_AFI,
.regs = {
.override = 0x188,
.security = 0x18c,
},
}, {
.name = "hdaw",
.sid = TEGRA186_SID_HDA,
.regs = {
.override = 0x1a8,
.security = 0x1ac,
},
}, {
.name = "mpcorew",
.sid = TEGRA186_SID_PASSTHROUGH,
.regs = {
.override = 0x1c8,
.security = 0x1cc,
},
}, {
.name = "sataw",
.sid = TEGRA186_SID_SATA,
.regs = {
.override = 0x1e8,
.security = 0x1ec,
},
}, {
.name = "ispra",
.sid = TEGRA186_SID_ISP,
.regs = {
.override = 0x220,
.security = 0x224,
},
}, {
.name = "ispwa",
.sid = TEGRA186_SID_ISP,
.regs = {
.override = 0x230,
.security = 0x234,
},
}, {
.name = "ispwb",
.sid = TEGRA186_SID_ISP,
.regs = {
.override = 0x238,
.security = 0x23c,
},
}, {
.name = "xusb_hostr",
.sid = TEGRA186_SID_XUSB_HOST,
.regs = {
.override = 0x250,
.security = 0x254,
},
}, {
.name = "xusb_hostw",
.sid = TEGRA186_SID_XUSB_HOST,
.regs = {
.override = 0x258,
.security = 0x25c,
},
}, {
.name = "xusb_devr",
.sid = TEGRA186_SID_XUSB_DEV,
.regs = {
.override = 0x260,
.security = 0x264,
},
}, {
.name = "xusb_devw",
.sid = TEGRA186_SID_XUSB_DEV,
.regs = {
.override = 0x268,
.security = 0x26c,
},
}, {
.name = "tsecsrd",
.sid = TEGRA186_SID_TSEC,
.regs = {
.override = 0x2a0,
.security = 0x2a4,
},
}, {
.name = "tsecswr",
.sid = TEGRA186_SID_TSEC,
.regs = {
.override = 0x2a8,
.security = 0x2ac,
},
}, {
.name = "gpusrd",
.sid = TEGRA186_SID_GPU,
.regs = {
.override = 0x2c0,
.security = 0x2c4,
},
}, {
.name = "gpuswr",
.sid = TEGRA186_SID_GPU,
.regs = {
.override = 0x2c8,
.security = 0x2cc,
},
}, {
.name = "sdmmcra",
.sid = TEGRA186_SID_SDMMC1,
.regs = {
.override = 0x300,
.security = 0x304,
},
}, {
.name = "sdmmcraa",
.sid = TEGRA186_SID_SDMMC2,
.regs = {
.override = 0x308,
.security = 0x30c,
},
}, {
.name = "sdmmcr",
.sid = TEGRA186_SID_SDMMC3,
.regs = {
.override = 0x310,
.security = 0x314,
},
}, {
.name = "sdmmcrab",
.sid = TEGRA186_SID_SDMMC4,
.regs = {
.override = 0x318,
.security = 0x31c,
},
}, {
.name = "sdmmcwa",
.sid = TEGRA186_SID_SDMMC1,
.regs = {
.override = 0x320,
.security = 0x324,
},
}, {
.name = "sdmmcwaa",
.sid = TEGRA186_SID_SDMMC2,
.regs = {
.override = 0x328,
.security = 0x32c,
},
}, {
.name = "sdmmcw",
.sid = TEGRA186_SID_SDMMC3,
.regs = {
.override = 0x330,
.security = 0x334,
},
}, {
.name = "sdmmcwab",
.sid = TEGRA186_SID_SDMMC4,
.regs = {
.override = 0x338,
.security = 0x33c,
},
}, {
.name = "vicsrd",
.sid = TEGRA186_SID_VIC,
.regs = {
.override = 0x360,
.security = 0x364,
},
}, {
.name = "vicswr",
.sid = TEGRA186_SID_VIC,
.regs = {
.override = 0x368,
.security = 0x36c,
},
}, {
.name = "viw",
.sid = TEGRA186_SID_VI,
.regs = {
.override = 0x390,
.security = 0x394,
},
}, {
.name = "nvdecsrd",
.sid = TEGRA186_SID_NVDEC,
.regs = {
.override = 0x3c0,
.security = 0x3c4,
},
}, {
.name = "nvdecswr",
.sid = TEGRA186_SID_NVDEC,
.regs = {
.override = 0x3c8,
.security = 0x3cc,
},
}, {
.name = "aper",
.sid = TEGRA186_SID_APE,
.regs = {
.override = 0x3d0,
.security = 0x3d4,
},
}, {
.name = "apew",
.sid = TEGRA186_SID_APE,
.regs = {
.override = 0x3d8,
.security = 0x3dc,
},
}, {
.name = "nvjpgsrd",
.sid = TEGRA186_SID_NVJPG,
.regs = {
.override = 0x3f0,
.security = 0x3f4,
},
}, {
.name = "nvjpgswr",
.sid = TEGRA186_SID_NVJPG,
.regs = {
.override = 0x3f8,
.security = 0x3fc,
},
}, {
.name = "sesrd",
.sid = TEGRA186_SID_SE,
.regs = {
.override = 0x400,
.security = 0x404,
},
}, {
.name = "seswr",
.sid = TEGRA186_SID_SE,
.regs = {
.override = 0x408,
.security = 0x40c,
},
}, {
.name = "etrr",
.sid = TEGRA186_SID_ETR,
.regs = {
.override = 0x420,
.security = 0x424,
},
}, {
.name = "etrw",
.sid = TEGRA186_SID_ETR,
.regs = {
.override = 0x428,
.security = 0x42c,
},
}, {
.name = "tsecsrdb",
.sid = TEGRA186_SID_TSECB,
.regs = {
.override = 0x430,
.security = 0x434,
},
}, {
.name = "tsecswrb",
.sid = TEGRA186_SID_TSECB,
.regs = {
.override = 0x438,
.security = 0x43c,
},
}, {
.name = "gpusrd2",
.sid = TEGRA186_SID_GPU,
.regs = {
.override = 0x440,
.security = 0x444,
},
}, {
.name = "gpuswr2",
.sid = TEGRA186_SID_GPU,
.regs = {
.override = 0x448,
.security = 0x44c,
},
}, {
.name = "axisr",
.sid = TEGRA186_SID_GPCDMA_0,
.regs = {
.override = 0x460,
.security = 0x464,
},
}, {
.name = "axisw",
.sid = TEGRA186_SID_GPCDMA_0,
.regs = {
.override = 0x468,
.security = 0x46c,
},
}, {
.name = "eqosr",
.sid = TEGRA186_SID_EQOS,
.regs = {
.override = 0x470,
.security = 0x474,
},
}, {
.name = "eqosw",
.sid = TEGRA186_SID_EQOS,
.regs = {
.override = 0x478,
.security = 0x47c,
},
}, {
.name = "ufshcr",
.sid = TEGRA186_SID_UFSHC,
.regs = {
.override = 0x480,
.security = 0x484,
},
}, {
.name = "ufshcw",
.sid = TEGRA186_SID_UFSHC,
.regs = {
.override = 0x488,
.security = 0x48c,
},
}, {
.name = "nvdisplayr",
.sid = TEGRA186_SID_NVDISPLAY,
.regs = {
.override = 0x490,
.security = 0x494,
},
}, {
.name = "bpmpr",
.sid = TEGRA186_SID_BPMP,
.regs = {
.override = 0x498,
.security = 0x49c,
},
}, {
.name = "bpmpw",
.sid = TEGRA186_SID_BPMP,
.regs = {
.override = 0x4a0,
.security = 0x4a4,
},
}, {
.name = "bpmpdmar",
.sid = TEGRA186_SID_BPMP,
.regs = {
.override = 0x4a8,
.security = 0x4ac,
},
}, {
.name = "bpmpdmaw",
.sid = TEGRA186_SID_BPMP,
.regs = {
.override = 0x4b0,
.security = 0x4b4,
},
}, {
.name = "aonr",
.sid = TEGRA186_SID_AON,
.regs = {
.override = 0x4b8,
.security = 0x4bc,
},
}, {
.name = "aonw",
.sid = TEGRA186_SID_AON,
.regs = {
.override = 0x4c0,
.security = 0x4c4,
},
}, {
.name = "aondmar",
.sid = TEGRA186_SID_AON,
.regs = {
.override = 0x4c8,
.security = 0x4cc,
},
}, {
.name = "aondmaw",
.sid = TEGRA186_SID_AON,
.regs = {
.override = 0x4d0,
.security = 0x4d4,
},
}, {
.name = "scer",
.sid = TEGRA186_SID_SCE,
.regs = {
.override = 0x4d8,
.security = 0x4dc,
},
}, {
.name = "scew",
.sid = TEGRA186_SID_SCE,
.regs = {
.override = 0x4e0,
.security = 0x4e4,
},
}, {
.name = "scedmar",
.sid = TEGRA186_SID_SCE,
.regs = {
.override = 0x4e8,
.security = 0x4ec,
},
}, {
.name = "scedmaw",
.sid = TEGRA186_SID_SCE,
.regs = {
.override = 0x4f0,
.security = 0x4f4,
},
}, {
.name = "apedmar",
.sid = TEGRA186_SID_APE,
.regs = {
.override = 0x4f8,
.security = 0x4fc,
},
}, {
.name = "apedmaw",
.sid = TEGRA186_SID_APE,
.regs = {
.override = 0x500,
.security = 0x504,
},
}, {
.name = "nvdisplayr1",
.sid = TEGRA186_SID_NVDISPLAY,
.regs = {
.override = 0x508,
.security = 0x50c,
},
}, {
.name = "vicsrd1",
.sid = TEGRA186_SID_VIC,
.regs = {
.override = 0x510,
.security = 0x514,
},
}, {
.name = "nvdecsrd1",
.sid = TEGRA186_SID_NVDEC,
.regs = {
.override = 0x518,
.security = 0x51c,
},
},
};
static int tegra186_mc_probe(struct platform_device *pdev)
{
struct resource *res;
struct tegra_mc *mc;
unsigned int i;
int err = 0;
mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
if (!mc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mc->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mc->regs))
return PTR_ERR(mc->regs);
mc->dev = &pdev->dev;
for (i = 0; i < ARRAY_SIZE(tegra186_mc_clients); i++) {
const struct tegra_mc_client *client = &tegra186_mc_clients[i];
u32 override, security;
override = readl(mc->regs + client->regs.override);
security = readl(mc->regs + client->regs.security);
dev_dbg(&pdev->dev, "client %s: override: %x security: %x\n",
client->name, override, security);
dev_dbg(&pdev->dev, "setting SID %u for %s\n", client->sid,
client->name);
writel(client->sid, mc->regs + client->regs.override);
override = readl(mc->regs + client->regs.override);
security = readl(mc->regs + client->regs.security);
dev_dbg(&pdev->dev, "client %s: override: %x security: %x\n",
client->name, override, security);
}
platform_set_drvdata(pdev, mc);
return err;
}
static const struct of_device_id tegra186_mc_of_match[] = {
{ .compatible = "nvidia,tegra186-mc", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, tegra186_mc_of_match);
static struct platform_driver tegra186_mc_driver = {
.driver = {
.name = "tegra186-mc",
.of_match_table = tegra186_mc_of_match,
.suppress_bind_attrs = true,
},
.prevent_deferred_probe = true,
.probe = tegra186_mc_probe,
};
module_platform_driver(tegra186_mc_driver);
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
MODULE_DESCRIPTION("NVIDIA Tegra186 Memory Controller driver");
MODULE_LICENSE("GPL v2");