1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2017-2021 NVIDIA CORPORATION. All rights reserved.
7 #include <linux/iommu.h>
8 #include <linux/module.h>
9 #include <linux/mod_devicetable.h>
11 #include <linux/of_platform.h>
12 #include <linux/platform_device.h>
14 #include <soc/tegra/mc.h>
16 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
17 #include <dt-bindings/memory/tegra186-mc.h>
22 #define MC_SID_STREAMID_OVERRIDE_MASK GENMASK(7, 0)
23 #define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
24 #define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
26 static int tegra186_mc_probe(struct tegra_mc *mc)
28 struct platform_device *pdev = to_platform_device(mc->dev);
33 mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "broadcast");
34 if (IS_ERR(mc->bcast_ch_regs)) {
35 if (PTR_ERR(mc->bcast_ch_regs) == -EINVAL) {
37 "Broadcast channel is missing, please update your device-tree\n");
38 mc->bcast_ch_regs = NULL;
42 return PTR_ERR(mc->bcast_ch_regs);
45 mc->ch_regs = devm_kcalloc(mc->dev, mc->soc->num_channels, sizeof(*mc->ch_regs),
50 for (i = 0; i < mc->soc->num_channels; i++) {
51 snprintf(name, sizeof(name), "ch%u", i);
53 mc->ch_regs[i] = devm_platform_ioremap_resource_byname(pdev, name);
54 if (IS_ERR(mc->ch_regs[i]))
55 return PTR_ERR(mc->ch_regs[i]);
59 err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
66 static void tegra186_mc_remove(struct tegra_mc *mc)
68 of_platform_depopulate(mc->dev);
71 #if IS_ENABLED(CONFIG_IOMMU_API)
72 static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
73 const struct tegra_mc_client *client,
78 value = readl(mc->regs + client->regs.sid.security);
79 if ((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0) {
81 * If the secure firmware has locked this down the override
82 * for this memory client, there's nothing we can do here.
84 if (value & MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED)
88 * Otherwise, try to set the override itself. Typically the
89 * secure firmware will never have set this configuration.
90 * Instead, it will either have disabled write access to
91 * this field, or it will already have set an explicit
94 WARN_ON((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0);
96 value |= MC_SID_STREAMID_SECURITY_OVERRIDE;
97 writel(value, mc->regs + client->regs.sid.security);
100 value = readl(mc->regs + client->regs.sid.override);
101 old = value & MC_SID_STREAMID_OVERRIDE_MASK;
104 dev_dbg(mc->dev, "overriding SID %x for %s with %x\n", old,
106 writel(sid, mc->regs + client->regs.sid.override);
111 static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
113 #if IS_ENABLED(CONFIG_IOMMU_API)
114 struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
115 struct of_phandle_args args;
116 unsigned int i, index = 0;
118 while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells",
120 if (args.np == mc->dev->of_node && args.args_count != 0) {
121 for (i = 0; i < mc->soc->num_clients; i++) {
122 const struct tegra_mc_client *client = &mc->soc->clients[i];
124 if (client->id == args.args[0]) {
125 u32 sid = fwspec->ids[0] & MC_SID_STREAMID_OVERRIDE_MASK;
127 tegra186_mc_client_sid_override(mc, client, sid);
139 const struct tegra_mc_ops tegra186_mc_ops = {
140 .probe = tegra186_mc_probe,
141 .remove = tegra186_mc_remove,
142 .probe_device = tegra186_mc_probe_device,
143 .handle_irq = tegra30_mc_handle_irq,
146 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
147 static const struct tegra_mc_client tegra186_mc_clients[] = {
149 .id = TEGRA186_MEMORY_CLIENT_PTCR,
151 .sid = TEGRA186_SID_PASSTHROUGH,
159 .id = TEGRA186_MEMORY_CLIENT_AFIR,
161 .sid = TEGRA186_SID_AFI,
169 .id = TEGRA186_MEMORY_CLIENT_HDAR,
171 .sid = TEGRA186_SID_HDA,
179 .id = TEGRA186_MEMORY_CLIENT_HOST1XDMAR,
180 .name = "host1xdmar",
181 .sid = TEGRA186_SID_HOST1X,
189 .id = TEGRA186_MEMORY_CLIENT_NVENCSRD,
191 .sid = TEGRA186_SID_NVENC,
199 .id = TEGRA186_MEMORY_CLIENT_SATAR,
201 .sid = TEGRA186_SID_SATA,
209 .id = TEGRA186_MEMORY_CLIENT_MPCORER,
211 .sid = TEGRA186_SID_PASSTHROUGH,
219 .id = TEGRA186_MEMORY_CLIENT_NVENCSWR,
221 .sid = TEGRA186_SID_NVENC,
229 .id = TEGRA186_MEMORY_CLIENT_AFIW,
231 .sid = TEGRA186_SID_AFI,
239 .id = TEGRA186_MEMORY_CLIENT_HDAW,
241 .sid = TEGRA186_SID_HDA,
249 .id = TEGRA186_MEMORY_CLIENT_MPCOREW,
251 .sid = TEGRA186_SID_PASSTHROUGH,
259 .id = TEGRA186_MEMORY_CLIENT_SATAW,
261 .sid = TEGRA186_SID_SATA,
269 .id = TEGRA186_MEMORY_CLIENT_ISPRA,
271 .sid = TEGRA186_SID_ISP,
279 .id = TEGRA186_MEMORY_CLIENT_ISPWA,
281 .sid = TEGRA186_SID_ISP,
289 .id = TEGRA186_MEMORY_CLIENT_ISPWB,
291 .sid = TEGRA186_SID_ISP,
299 .id = TEGRA186_MEMORY_CLIENT_XUSB_HOSTR,
300 .name = "xusb_hostr",
301 .sid = TEGRA186_SID_XUSB_HOST,
309 .id = TEGRA186_MEMORY_CLIENT_XUSB_HOSTW,
310 .name = "xusb_hostw",
311 .sid = TEGRA186_SID_XUSB_HOST,
319 .id = TEGRA186_MEMORY_CLIENT_XUSB_DEVR,
321 .sid = TEGRA186_SID_XUSB_DEV,
329 .id = TEGRA186_MEMORY_CLIENT_XUSB_DEVW,
331 .sid = TEGRA186_SID_XUSB_DEV,
339 .id = TEGRA186_MEMORY_CLIENT_TSECSRD,
341 .sid = TEGRA186_SID_TSEC,
349 .id = TEGRA186_MEMORY_CLIENT_TSECSWR,
351 .sid = TEGRA186_SID_TSEC,
359 .id = TEGRA186_MEMORY_CLIENT_GPUSRD,
361 .sid = TEGRA186_SID_GPU,
369 .id = TEGRA186_MEMORY_CLIENT_GPUSWR,
371 .sid = TEGRA186_SID_GPU,
379 .id = TEGRA186_MEMORY_CLIENT_SDMMCRA,
381 .sid = TEGRA186_SID_SDMMC1,
389 .id = TEGRA186_MEMORY_CLIENT_SDMMCRAA,
391 .sid = TEGRA186_SID_SDMMC2,
399 .id = TEGRA186_MEMORY_CLIENT_SDMMCR,
401 .sid = TEGRA186_SID_SDMMC3,
409 .id = TEGRA186_MEMORY_CLIENT_SDMMCRAB,
411 .sid = TEGRA186_SID_SDMMC4,
419 .id = TEGRA186_MEMORY_CLIENT_SDMMCWA,
421 .sid = TEGRA186_SID_SDMMC1,
429 .id = TEGRA186_MEMORY_CLIENT_SDMMCWAA,
431 .sid = TEGRA186_SID_SDMMC2,
439 .id = TEGRA186_MEMORY_CLIENT_SDMMCW,
441 .sid = TEGRA186_SID_SDMMC3,
449 .id = TEGRA186_MEMORY_CLIENT_SDMMCWAB,
451 .sid = TEGRA186_SID_SDMMC4,
459 .id = TEGRA186_MEMORY_CLIENT_VICSRD,
461 .sid = TEGRA186_SID_VIC,
469 .id = TEGRA186_MEMORY_CLIENT_VICSWR,
471 .sid = TEGRA186_SID_VIC,
479 .id = TEGRA186_MEMORY_CLIENT_VIW,
481 .sid = TEGRA186_SID_VI,
489 .id = TEGRA186_MEMORY_CLIENT_NVDECSRD,
491 .sid = TEGRA186_SID_NVDEC,
499 .id = TEGRA186_MEMORY_CLIENT_NVDECSWR,
501 .sid = TEGRA186_SID_NVDEC,
509 .id = TEGRA186_MEMORY_CLIENT_APER,
511 .sid = TEGRA186_SID_APE,
519 .id = TEGRA186_MEMORY_CLIENT_APEW,
521 .sid = TEGRA186_SID_APE,
529 .id = TEGRA186_MEMORY_CLIENT_NVJPGSRD,
531 .sid = TEGRA186_SID_NVJPG,
539 .id = TEGRA186_MEMORY_CLIENT_NVJPGSWR,
541 .sid = TEGRA186_SID_NVJPG,
549 .id = TEGRA186_MEMORY_CLIENT_SESRD,
551 .sid = TEGRA186_SID_SE,
559 .id = TEGRA186_MEMORY_CLIENT_SESWR,
561 .sid = TEGRA186_SID_SE,
569 .id = TEGRA186_MEMORY_CLIENT_ETRR,
571 .sid = TEGRA186_SID_ETR,
579 .id = TEGRA186_MEMORY_CLIENT_ETRW,
581 .sid = TEGRA186_SID_ETR,
589 .id = TEGRA186_MEMORY_CLIENT_TSECSRDB,
591 .sid = TEGRA186_SID_TSECB,
599 .id = TEGRA186_MEMORY_CLIENT_TSECSWRB,
601 .sid = TEGRA186_SID_TSECB,
609 .id = TEGRA186_MEMORY_CLIENT_GPUSRD2,
611 .sid = TEGRA186_SID_GPU,
619 .id = TEGRA186_MEMORY_CLIENT_GPUSWR2,
621 .sid = TEGRA186_SID_GPU,
629 .id = TEGRA186_MEMORY_CLIENT_AXISR,
631 .sid = TEGRA186_SID_GPCDMA_0,
639 .id = TEGRA186_MEMORY_CLIENT_AXISW,
641 .sid = TEGRA186_SID_GPCDMA_0,
649 .id = TEGRA186_MEMORY_CLIENT_EQOSR,
651 .sid = TEGRA186_SID_EQOS,
659 .id = TEGRA186_MEMORY_CLIENT_EQOSW,
661 .sid = TEGRA186_SID_EQOS,
669 .id = TEGRA186_MEMORY_CLIENT_UFSHCR,
671 .sid = TEGRA186_SID_UFSHC,
679 .id = TEGRA186_MEMORY_CLIENT_UFSHCW,
681 .sid = TEGRA186_SID_UFSHC,
689 .id = TEGRA186_MEMORY_CLIENT_NVDISPLAYR,
690 .name = "nvdisplayr",
691 .sid = TEGRA186_SID_NVDISPLAY,
699 .id = TEGRA186_MEMORY_CLIENT_BPMPR,
701 .sid = TEGRA186_SID_BPMP,
709 .id = TEGRA186_MEMORY_CLIENT_BPMPW,
711 .sid = TEGRA186_SID_BPMP,
719 .id = TEGRA186_MEMORY_CLIENT_BPMPDMAR,
721 .sid = TEGRA186_SID_BPMP,
729 .id = TEGRA186_MEMORY_CLIENT_BPMPDMAW,
731 .sid = TEGRA186_SID_BPMP,
739 .id = TEGRA186_MEMORY_CLIENT_AONR,
741 .sid = TEGRA186_SID_AON,
749 .id = TEGRA186_MEMORY_CLIENT_AONW,
751 .sid = TEGRA186_SID_AON,
759 .id = TEGRA186_MEMORY_CLIENT_AONDMAR,
761 .sid = TEGRA186_SID_AON,
769 .id = TEGRA186_MEMORY_CLIENT_AONDMAW,
771 .sid = TEGRA186_SID_AON,
779 .id = TEGRA186_MEMORY_CLIENT_SCER,
781 .sid = TEGRA186_SID_SCE,
789 .id = TEGRA186_MEMORY_CLIENT_SCEW,
791 .sid = TEGRA186_SID_SCE,
799 .id = TEGRA186_MEMORY_CLIENT_SCEDMAR,
801 .sid = TEGRA186_SID_SCE,
809 .id = TEGRA186_MEMORY_CLIENT_SCEDMAW,
811 .sid = TEGRA186_SID_SCE,
819 .id = TEGRA186_MEMORY_CLIENT_APEDMAR,
821 .sid = TEGRA186_SID_APE,
829 .id = TEGRA186_MEMORY_CLIENT_APEDMAW,
831 .sid = TEGRA186_SID_APE,
839 .id = TEGRA186_MEMORY_CLIENT_NVDISPLAYR1,
840 .name = "nvdisplayr1",
841 .sid = TEGRA186_SID_NVDISPLAY,
849 .id = TEGRA186_MEMORY_CLIENT_VICSRD1,
851 .sid = TEGRA186_SID_VIC,
859 .id = TEGRA186_MEMORY_CLIENT_NVDECSRD1,
861 .sid = TEGRA186_SID_NVDEC,
871 const struct tegra_mc_soc tegra186_mc_soc = {
872 .num_clients = ARRAY_SIZE(tegra186_mc_clients),
873 .clients = tegra186_mc_clients,
874 .num_address_bits = 40,
876 .client_id_mask = 0xff,
877 .intmask = MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
878 MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
879 MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
880 .ops = &tegra186_mc_ops,
881 .ch_intmask = 0x0000000f,
882 .global_intstatus_channel_shift = 0,