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>
10 #include <linux/of_device.h>
11 #include <linux/platform_device.h>
13 #include <soc/tegra/mc.h>
15 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
16 #include <dt-bindings/memory/tegra186-mc.h>
21 #define MC_SID_STREAMID_OVERRIDE_MASK GENMASK(7, 0)
22 #define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
23 #define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
25 static void tegra186_mc_program_sid(struct tegra_mc *mc)
29 for (i = 0; i < mc->soc->num_clients; i++) {
30 const struct tegra_mc_client *client = &mc->soc->clients[i];
31 u32 override, security;
33 override = readl(mc->regs + client->regs.sid.override);
34 security = readl(mc->regs + client->regs.sid.security);
36 dev_dbg(mc->dev, "client %s: override: %x security: %x\n",
37 client->name, override, security);
39 dev_dbg(mc->dev, "setting SID %u for %s\n", client->sid,
41 writel(client->sid, mc->regs + client->regs.sid.override);
43 override = readl(mc->regs + client->regs.sid.override);
44 security = readl(mc->regs + client->regs.sid.security);
46 dev_dbg(mc->dev, "client %s: override: %x security: %x\n",
47 client->name, override, security);
51 static int tegra186_mc_probe(struct tegra_mc *mc)
53 struct platform_device *pdev = to_platform_device(mc->dev);
58 mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "broadcast");
59 if (IS_ERR(mc->bcast_ch_regs)) {
60 if (PTR_ERR(mc->bcast_ch_regs) == -EINVAL) {
62 "Broadcast channel is missing, please update your device-tree\n");
63 mc->bcast_ch_regs = NULL;
67 return PTR_ERR(mc->bcast_ch_regs);
70 mc->ch_regs = devm_kcalloc(mc->dev, mc->soc->num_channels, sizeof(*mc->ch_regs),
75 for (i = 0; i < mc->soc->num_channels; i++) {
76 snprintf(name, sizeof(name), "ch%u", i);
78 mc->ch_regs[i] = devm_platform_ioremap_resource_byname(pdev, name);
79 if (IS_ERR(mc->ch_regs[i]))
80 return PTR_ERR(mc->ch_regs[i]);
84 err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
88 tegra186_mc_program_sid(mc);
93 static void tegra186_mc_remove(struct tegra_mc *mc)
95 of_platform_depopulate(mc->dev);
98 static int tegra186_mc_resume(struct tegra_mc *mc)
100 tegra186_mc_program_sid(mc);
105 #if IS_ENABLED(CONFIG_IOMMU_API)
106 static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
107 const struct tegra_mc_client *client,
112 value = readl(mc->regs + client->regs.sid.security);
113 if ((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0) {
115 * If the secure firmware has locked this down the override
116 * for this memory client, there's nothing we can do here.
118 if (value & MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED)
122 * Otherwise, try to set the override itself. Typically the
123 * secure firmware will never have set this configuration.
124 * Instead, it will either have disabled write access to
125 * this field, or it will already have set an explicit
128 WARN_ON((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0);
130 value |= MC_SID_STREAMID_SECURITY_OVERRIDE;
131 writel(value, mc->regs + client->regs.sid.security);
134 value = readl(mc->regs + client->regs.sid.override);
135 old = value & MC_SID_STREAMID_OVERRIDE_MASK;
138 dev_dbg(mc->dev, "overriding SID %x for %s with %x\n", old,
140 writel(sid, mc->regs + client->regs.sid.override);
145 static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
147 #if IS_ENABLED(CONFIG_IOMMU_API)
148 struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
149 struct of_phandle_args args;
150 unsigned int i, index = 0;
152 while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells",
154 if (args.np == mc->dev->of_node && args.args_count != 0) {
155 for (i = 0; i < mc->soc->num_clients; i++) {
156 const struct tegra_mc_client *client = &mc->soc->clients[i];
158 if (client->id == args.args[0]) {
159 u32 sid = fwspec->ids[0] & MC_SID_STREAMID_OVERRIDE_MASK;
161 tegra186_mc_client_sid_override(mc, client, sid);
173 const struct tegra_mc_ops tegra186_mc_ops = {
174 .probe = tegra186_mc_probe,
175 .remove = tegra186_mc_remove,
176 .resume = tegra186_mc_resume,
177 .probe_device = tegra186_mc_probe_device,
178 .handle_irq = tegra30_mc_handle_irq,
181 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
182 static const struct tegra_mc_client tegra186_mc_clients[] = {
184 .id = TEGRA186_MEMORY_CLIENT_PTCR,
186 .sid = TEGRA186_SID_PASSTHROUGH,
194 .id = TEGRA186_MEMORY_CLIENT_AFIR,
196 .sid = TEGRA186_SID_AFI,
204 .id = TEGRA186_MEMORY_CLIENT_HDAR,
206 .sid = TEGRA186_SID_HDA,
214 .id = TEGRA186_MEMORY_CLIENT_HOST1XDMAR,
215 .name = "host1xdmar",
216 .sid = TEGRA186_SID_HOST1X,
224 .id = TEGRA186_MEMORY_CLIENT_NVENCSRD,
226 .sid = TEGRA186_SID_NVENC,
234 .id = TEGRA186_MEMORY_CLIENT_SATAR,
236 .sid = TEGRA186_SID_SATA,
244 .id = TEGRA186_MEMORY_CLIENT_MPCORER,
246 .sid = TEGRA186_SID_PASSTHROUGH,
254 .id = TEGRA186_MEMORY_CLIENT_NVENCSWR,
256 .sid = TEGRA186_SID_NVENC,
264 .id = TEGRA186_MEMORY_CLIENT_AFIW,
266 .sid = TEGRA186_SID_AFI,
274 .id = TEGRA186_MEMORY_CLIENT_HDAW,
276 .sid = TEGRA186_SID_HDA,
284 .id = TEGRA186_MEMORY_CLIENT_MPCOREW,
286 .sid = TEGRA186_SID_PASSTHROUGH,
294 .id = TEGRA186_MEMORY_CLIENT_SATAW,
296 .sid = TEGRA186_SID_SATA,
304 .id = TEGRA186_MEMORY_CLIENT_ISPRA,
306 .sid = TEGRA186_SID_ISP,
314 .id = TEGRA186_MEMORY_CLIENT_ISPWA,
316 .sid = TEGRA186_SID_ISP,
324 .id = TEGRA186_MEMORY_CLIENT_ISPWB,
326 .sid = TEGRA186_SID_ISP,
334 .id = TEGRA186_MEMORY_CLIENT_XUSB_HOSTR,
335 .name = "xusb_hostr",
336 .sid = TEGRA186_SID_XUSB_HOST,
344 .id = TEGRA186_MEMORY_CLIENT_XUSB_HOSTW,
345 .name = "xusb_hostw",
346 .sid = TEGRA186_SID_XUSB_HOST,
354 .id = TEGRA186_MEMORY_CLIENT_XUSB_DEVR,
356 .sid = TEGRA186_SID_XUSB_DEV,
364 .id = TEGRA186_MEMORY_CLIENT_XUSB_DEVW,
366 .sid = TEGRA186_SID_XUSB_DEV,
374 .id = TEGRA186_MEMORY_CLIENT_TSECSRD,
376 .sid = TEGRA186_SID_TSEC,
384 .id = TEGRA186_MEMORY_CLIENT_TSECSWR,
386 .sid = TEGRA186_SID_TSEC,
394 .id = TEGRA186_MEMORY_CLIENT_GPUSRD,
396 .sid = TEGRA186_SID_GPU,
404 .id = TEGRA186_MEMORY_CLIENT_GPUSWR,
406 .sid = TEGRA186_SID_GPU,
414 .id = TEGRA186_MEMORY_CLIENT_SDMMCRA,
416 .sid = TEGRA186_SID_SDMMC1,
424 .id = TEGRA186_MEMORY_CLIENT_SDMMCRAA,
426 .sid = TEGRA186_SID_SDMMC2,
434 .id = TEGRA186_MEMORY_CLIENT_SDMMCR,
436 .sid = TEGRA186_SID_SDMMC3,
444 .id = TEGRA186_MEMORY_CLIENT_SDMMCRAB,
446 .sid = TEGRA186_SID_SDMMC4,
454 .id = TEGRA186_MEMORY_CLIENT_SDMMCWA,
456 .sid = TEGRA186_SID_SDMMC1,
464 .id = TEGRA186_MEMORY_CLIENT_SDMMCWAA,
466 .sid = TEGRA186_SID_SDMMC2,
474 .id = TEGRA186_MEMORY_CLIENT_SDMMCW,
476 .sid = TEGRA186_SID_SDMMC3,
484 .id = TEGRA186_MEMORY_CLIENT_SDMMCWAB,
486 .sid = TEGRA186_SID_SDMMC4,
494 .id = TEGRA186_MEMORY_CLIENT_VICSRD,
496 .sid = TEGRA186_SID_VIC,
504 .id = TEGRA186_MEMORY_CLIENT_VICSWR,
506 .sid = TEGRA186_SID_VIC,
514 .id = TEGRA186_MEMORY_CLIENT_VIW,
516 .sid = TEGRA186_SID_VI,
524 .id = TEGRA186_MEMORY_CLIENT_NVDECSRD,
526 .sid = TEGRA186_SID_NVDEC,
534 .id = TEGRA186_MEMORY_CLIENT_NVDECSWR,
536 .sid = TEGRA186_SID_NVDEC,
544 .id = TEGRA186_MEMORY_CLIENT_APER,
546 .sid = TEGRA186_SID_APE,
554 .id = TEGRA186_MEMORY_CLIENT_APEW,
556 .sid = TEGRA186_SID_APE,
564 .id = TEGRA186_MEMORY_CLIENT_NVJPGSRD,
566 .sid = TEGRA186_SID_NVJPG,
574 .id = TEGRA186_MEMORY_CLIENT_NVJPGSWR,
576 .sid = TEGRA186_SID_NVJPG,
584 .id = TEGRA186_MEMORY_CLIENT_SESRD,
586 .sid = TEGRA186_SID_SE,
594 .id = TEGRA186_MEMORY_CLIENT_SESWR,
596 .sid = TEGRA186_SID_SE,
604 .id = TEGRA186_MEMORY_CLIENT_ETRR,
606 .sid = TEGRA186_SID_ETR,
614 .id = TEGRA186_MEMORY_CLIENT_ETRW,
616 .sid = TEGRA186_SID_ETR,
624 .id = TEGRA186_MEMORY_CLIENT_TSECSRDB,
626 .sid = TEGRA186_SID_TSECB,
634 .id = TEGRA186_MEMORY_CLIENT_TSECSWRB,
636 .sid = TEGRA186_SID_TSECB,
644 .id = TEGRA186_MEMORY_CLIENT_GPUSRD2,
646 .sid = TEGRA186_SID_GPU,
654 .id = TEGRA186_MEMORY_CLIENT_GPUSWR2,
656 .sid = TEGRA186_SID_GPU,
664 .id = TEGRA186_MEMORY_CLIENT_AXISR,
666 .sid = TEGRA186_SID_GPCDMA_0,
674 .id = TEGRA186_MEMORY_CLIENT_AXISW,
676 .sid = TEGRA186_SID_GPCDMA_0,
684 .id = TEGRA186_MEMORY_CLIENT_EQOSR,
686 .sid = TEGRA186_SID_EQOS,
694 .id = TEGRA186_MEMORY_CLIENT_EQOSW,
696 .sid = TEGRA186_SID_EQOS,
704 .id = TEGRA186_MEMORY_CLIENT_UFSHCR,
706 .sid = TEGRA186_SID_UFSHC,
714 .id = TEGRA186_MEMORY_CLIENT_UFSHCW,
716 .sid = TEGRA186_SID_UFSHC,
724 .id = TEGRA186_MEMORY_CLIENT_NVDISPLAYR,
725 .name = "nvdisplayr",
726 .sid = TEGRA186_SID_NVDISPLAY,
734 .id = TEGRA186_MEMORY_CLIENT_BPMPR,
736 .sid = TEGRA186_SID_BPMP,
744 .id = TEGRA186_MEMORY_CLIENT_BPMPW,
746 .sid = TEGRA186_SID_BPMP,
754 .id = TEGRA186_MEMORY_CLIENT_BPMPDMAR,
756 .sid = TEGRA186_SID_BPMP,
764 .id = TEGRA186_MEMORY_CLIENT_BPMPDMAW,
766 .sid = TEGRA186_SID_BPMP,
774 .id = TEGRA186_MEMORY_CLIENT_AONR,
776 .sid = TEGRA186_SID_AON,
784 .id = TEGRA186_MEMORY_CLIENT_AONW,
786 .sid = TEGRA186_SID_AON,
794 .id = TEGRA186_MEMORY_CLIENT_AONDMAR,
796 .sid = TEGRA186_SID_AON,
804 .id = TEGRA186_MEMORY_CLIENT_AONDMAW,
806 .sid = TEGRA186_SID_AON,
814 .id = TEGRA186_MEMORY_CLIENT_SCER,
816 .sid = TEGRA186_SID_SCE,
824 .id = TEGRA186_MEMORY_CLIENT_SCEW,
826 .sid = TEGRA186_SID_SCE,
834 .id = TEGRA186_MEMORY_CLIENT_SCEDMAR,
836 .sid = TEGRA186_SID_SCE,
844 .id = TEGRA186_MEMORY_CLIENT_SCEDMAW,
846 .sid = TEGRA186_SID_SCE,
854 .id = TEGRA186_MEMORY_CLIENT_APEDMAR,
856 .sid = TEGRA186_SID_APE,
864 .id = TEGRA186_MEMORY_CLIENT_APEDMAW,
866 .sid = TEGRA186_SID_APE,
874 .id = TEGRA186_MEMORY_CLIENT_NVDISPLAYR1,
875 .name = "nvdisplayr1",
876 .sid = TEGRA186_SID_NVDISPLAY,
884 .id = TEGRA186_MEMORY_CLIENT_VICSRD1,
886 .sid = TEGRA186_SID_VIC,
894 .id = TEGRA186_MEMORY_CLIENT_NVDECSRD1,
896 .sid = TEGRA186_SID_NVDEC,
906 const struct tegra_mc_soc tegra186_mc_soc = {
907 .num_clients = ARRAY_SIZE(tegra186_mc_clients),
908 .clients = tegra186_mc_clients,
909 .num_address_bits = 40,
911 .client_id_mask = 0xff,
912 .intmask = MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
913 MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
914 MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
915 .ops = &tegra186_mc_ops,
916 .ch_intmask = 0x0000000f,
917 .global_intstatus_channel_shift = 0,