diff options
author | Thierry Reding <treding@nvidia.com> | 2017-12-13 12:58:21 +0100 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2017-12-13 12:58:21 +0100 |
commit | 02b0cc52c0c3c89641276cb1e7abddd35e036923 (patch) | |
tree | 86397ab8d4b03c0b18eacd1049aa1168bb792d07 /drivers/memory/tegra | |
parent | fc17a91fd18ce0567d9b29c30017fcfb2079572b (diff) | |
download | linux-02b0cc52c0c3c89641276cb1e7abddd35e036923.tar.gz linux-02b0cc52c0c3c89641276cb1e7abddd35e036923.tar.bz2 linux-02b0cc52c0c3c89641276cb1e7abddd35e036923.zip |
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>
Diffstat (limited to 'drivers/memory/tegra')
-rw-r--r-- | drivers/memory/tegra/Makefile | 1 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra186.c | 600 |
2 files changed, 601 insertions, 0 deletions
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile index b44e8627a5e0..ce87a9470034 100644 --- a/drivers/memory/tegra/Makefile +++ b/drivers/memory/tegra/Makefile @@ -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 diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c new file mode 100644 index 000000000000..7254fb596979 --- /dev/null +++ b/drivers/memory/tegra/tegra186.c @@ -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"); |