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>
19 #define MC_SID_STREAMID_OVERRIDE_MASK GENMASK(7, 0)
20 #define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
21 #define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
23 static void tegra186_mc_program_sid(struct tegra_mc *mc)
27 for (i = 0; i < mc->soc->num_clients; i++) {
28 const struct tegra_mc_client *client = &mc->soc->clients[i];
29 u32 override, security;
31 override = readl(mc->regs + client->regs.sid.override);
32 security = readl(mc->regs + client->regs.sid.security);
34 dev_dbg(mc->dev, "client %s: override: %x security: %x\n",
35 client->name, override, security);
37 dev_dbg(mc->dev, "setting SID %u for %s\n", client->sid,
39 writel(client->sid, mc->regs + client->regs.sid.override);
41 override = readl(mc->regs + client->regs.sid.override);
42 security = readl(mc->regs + client->regs.sid.security);
44 dev_dbg(mc->dev, "client %s: override: %x security: %x\n",
45 client->name, override, security);
49 static int tegra186_mc_probe(struct tegra_mc *mc)
53 err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
57 tegra186_mc_program_sid(mc);
62 static void tegra186_mc_remove(struct tegra_mc *mc)
64 of_platform_depopulate(mc->dev);
67 static int tegra186_mc_resume(struct tegra_mc *mc)
69 tegra186_mc_program_sid(mc);
74 #if IS_ENABLED(CONFIG_IOMMU_API)
75 static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
76 const struct tegra_mc_client *client,
81 value = readl(mc->regs + client->regs.sid.security);
82 if ((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0) {
84 * If the secure firmware has locked this down the override
85 * for this memory client, there's nothing we can do here.
87 if (value & MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED)
91 * Otherwise, try to set the override itself. Typically the
92 * secure firmware will never have set this configuration.
93 * Instead, it will either have disabled write access to
94 * this field, or it will already have set an explicit
97 WARN_ON((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0);
99 value |= MC_SID_STREAMID_SECURITY_OVERRIDE;
100 writel(value, mc->regs + client->regs.sid.security);
103 value = readl(mc->regs + client->regs.sid.override);
104 old = value & MC_SID_STREAMID_OVERRIDE_MASK;
107 dev_dbg(mc->dev, "overriding SID %x for %s with %x\n", old,
109 writel(sid, mc->regs + client->regs.sid.override);
114 static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
116 #if IS_ENABLED(CONFIG_IOMMU_API)
117 struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
118 struct of_phandle_args args;
119 unsigned int i, index = 0;
121 while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells",
123 if (args.np == mc->dev->of_node && args.args_count != 0) {
124 for (i = 0; i < mc->soc->num_clients; i++) {
125 const struct tegra_mc_client *client = &mc->soc->clients[i];
127 if (client->id == args.args[0]) {
128 u32 sid = fwspec->ids[0] & MC_SID_STREAMID_OVERRIDE_MASK;
130 tegra186_mc_client_sid_override(mc, client, sid);
142 const struct tegra_mc_ops tegra186_mc_ops = {
143 .probe = tegra186_mc_probe,
144 .remove = tegra186_mc_remove,
145 .resume = tegra186_mc_resume,
146 .probe_device = tegra186_mc_probe_device,
149 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
150 static const struct tegra_mc_client tegra186_mc_clients[] = {
152 .id = TEGRA186_MEMORY_CLIENT_PTCR,
154 .sid = TEGRA186_SID_PASSTHROUGH,
162 .id = TEGRA186_MEMORY_CLIENT_AFIR,
164 .sid = TEGRA186_SID_AFI,
172 .id = TEGRA186_MEMORY_CLIENT_HDAR,
174 .sid = TEGRA186_SID_HDA,
182 .id = TEGRA186_MEMORY_CLIENT_HOST1XDMAR,
183 .name = "host1xdmar",
184 .sid = TEGRA186_SID_HOST1X,
192 .id = TEGRA186_MEMORY_CLIENT_NVENCSRD,
194 .sid = TEGRA186_SID_NVENC,
202 .id = TEGRA186_MEMORY_CLIENT_SATAR,
204 .sid = TEGRA186_SID_SATA,
212 .id = TEGRA186_MEMORY_CLIENT_MPCORER,
214 .sid = TEGRA186_SID_PASSTHROUGH,
222 .id = TEGRA186_MEMORY_CLIENT_NVENCSWR,
224 .sid = TEGRA186_SID_NVENC,
232 .id = TEGRA186_MEMORY_CLIENT_AFIW,
234 .sid = TEGRA186_SID_AFI,
242 .id = TEGRA186_MEMORY_CLIENT_HDAW,
244 .sid = TEGRA186_SID_HDA,
252 .id = TEGRA186_MEMORY_CLIENT_MPCOREW,
254 .sid = TEGRA186_SID_PASSTHROUGH,
262 .id = TEGRA186_MEMORY_CLIENT_SATAW,
264 .sid = TEGRA186_SID_SATA,
272 .id = TEGRA186_MEMORY_CLIENT_ISPRA,
274 .sid = TEGRA186_SID_ISP,
282 .id = TEGRA186_MEMORY_CLIENT_ISPWA,
284 .sid = TEGRA186_SID_ISP,
292 .id = TEGRA186_MEMORY_CLIENT_ISPWB,
294 .sid = TEGRA186_SID_ISP,
302 .id = TEGRA186_MEMORY_CLIENT_XUSB_HOSTR,
303 .name = "xusb_hostr",
304 .sid = TEGRA186_SID_XUSB_HOST,
312 .id = TEGRA186_MEMORY_CLIENT_XUSB_HOSTW,
313 .name = "xusb_hostw",
314 .sid = TEGRA186_SID_XUSB_HOST,
322 .id = TEGRA186_MEMORY_CLIENT_XUSB_DEVR,
324 .sid = TEGRA186_SID_XUSB_DEV,
332 .id = TEGRA186_MEMORY_CLIENT_XUSB_DEVW,
334 .sid = TEGRA186_SID_XUSB_DEV,
342 .id = TEGRA186_MEMORY_CLIENT_TSECSRD,
344 .sid = TEGRA186_SID_TSEC,
352 .id = TEGRA186_MEMORY_CLIENT_TSECSWR,
354 .sid = TEGRA186_SID_TSEC,
362 .id = TEGRA186_MEMORY_CLIENT_GPUSRD,
364 .sid = TEGRA186_SID_GPU,
372 .id = TEGRA186_MEMORY_CLIENT_GPUSWR,
374 .sid = TEGRA186_SID_GPU,
382 .id = TEGRA186_MEMORY_CLIENT_SDMMCRA,
384 .sid = TEGRA186_SID_SDMMC1,
392 .id = TEGRA186_MEMORY_CLIENT_SDMMCRAA,
394 .sid = TEGRA186_SID_SDMMC2,
402 .id = TEGRA186_MEMORY_CLIENT_SDMMCR,
404 .sid = TEGRA186_SID_SDMMC3,
412 .id = TEGRA186_MEMORY_CLIENT_SDMMCRAB,
414 .sid = TEGRA186_SID_SDMMC4,
422 .id = TEGRA186_MEMORY_CLIENT_SDMMCWA,
424 .sid = TEGRA186_SID_SDMMC1,
432 .id = TEGRA186_MEMORY_CLIENT_SDMMCWAA,
434 .sid = TEGRA186_SID_SDMMC2,
442 .id = TEGRA186_MEMORY_CLIENT_SDMMCW,
444 .sid = TEGRA186_SID_SDMMC3,
452 .id = TEGRA186_MEMORY_CLIENT_SDMMCWAB,
454 .sid = TEGRA186_SID_SDMMC4,
462 .id = TEGRA186_MEMORY_CLIENT_VICSRD,
464 .sid = TEGRA186_SID_VIC,
472 .id = TEGRA186_MEMORY_CLIENT_VICSWR,
474 .sid = TEGRA186_SID_VIC,
482 .id = TEGRA186_MEMORY_CLIENT_VIW,
484 .sid = TEGRA186_SID_VI,
492 .id = TEGRA186_MEMORY_CLIENT_NVDECSRD,
494 .sid = TEGRA186_SID_NVDEC,
502 .id = TEGRA186_MEMORY_CLIENT_NVDECSWR,
504 .sid = TEGRA186_SID_NVDEC,
512 .id = TEGRA186_MEMORY_CLIENT_APER,
514 .sid = TEGRA186_SID_APE,
522 .id = TEGRA186_MEMORY_CLIENT_APEW,
524 .sid = TEGRA186_SID_APE,
532 .id = TEGRA186_MEMORY_CLIENT_NVJPGSRD,
534 .sid = TEGRA186_SID_NVJPG,
542 .id = TEGRA186_MEMORY_CLIENT_NVJPGSWR,
544 .sid = TEGRA186_SID_NVJPG,
552 .id = TEGRA186_MEMORY_CLIENT_SESRD,
554 .sid = TEGRA186_SID_SE,
562 .id = TEGRA186_MEMORY_CLIENT_SESWR,
564 .sid = TEGRA186_SID_SE,
572 .id = TEGRA186_MEMORY_CLIENT_ETRR,
574 .sid = TEGRA186_SID_ETR,
582 .id = TEGRA186_MEMORY_CLIENT_ETRW,
584 .sid = TEGRA186_SID_ETR,
592 .id = TEGRA186_MEMORY_CLIENT_TSECSRDB,
594 .sid = TEGRA186_SID_TSECB,
602 .id = TEGRA186_MEMORY_CLIENT_TSECSWRB,
604 .sid = TEGRA186_SID_TSECB,
612 .id = TEGRA186_MEMORY_CLIENT_GPUSRD2,
614 .sid = TEGRA186_SID_GPU,
622 .id = TEGRA186_MEMORY_CLIENT_GPUSWR2,
624 .sid = TEGRA186_SID_GPU,
632 .id = TEGRA186_MEMORY_CLIENT_AXISR,
634 .sid = TEGRA186_SID_GPCDMA_0,
642 .id = TEGRA186_MEMORY_CLIENT_AXISW,
644 .sid = TEGRA186_SID_GPCDMA_0,
652 .id = TEGRA186_MEMORY_CLIENT_EQOSR,
654 .sid = TEGRA186_SID_EQOS,
662 .id = TEGRA186_MEMORY_CLIENT_EQOSW,
664 .sid = TEGRA186_SID_EQOS,
672 .id = TEGRA186_MEMORY_CLIENT_UFSHCR,
674 .sid = TEGRA186_SID_UFSHC,
682 .id = TEGRA186_MEMORY_CLIENT_UFSHCW,
684 .sid = TEGRA186_SID_UFSHC,
692 .id = TEGRA186_MEMORY_CLIENT_NVDISPLAYR,
693 .name = "nvdisplayr",
694 .sid = TEGRA186_SID_NVDISPLAY,
702 .id = TEGRA186_MEMORY_CLIENT_BPMPR,
704 .sid = TEGRA186_SID_BPMP,
712 .id = TEGRA186_MEMORY_CLIENT_BPMPW,
714 .sid = TEGRA186_SID_BPMP,
722 .id = TEGRA186_MEMORY_CLIENT_BPMPDMAR,
724 .sid = TEGRA186_SID_BPMP,
732 .id = TEGRA186_MEMORY_CLIENT_BPMPDMAW,
734 .sid = TEGRA186_SID_BPMP,
742 .id = TEGRA186_MEMORY_CLIENT_AONR,
744 .sid = TEGRA186_SID_AON,
752 .id = TEGRA186_MEMORY_CLIENT_AONW,
754 .sid = TEGRA186_SID_AON,
762 .id = TEGRA186_MEMORY_CLIENT_AONDMAR,
764 .sid = TEGRA186_SID_AON,
772 .id = TEGRA186_MEMORY_CLIENT_AONDMAW,
774 .sid = TEGRA186_SID_AON,
782 .id = TEGRA186_MEMORY_CLIENT_SCER,
784 .sid = TEGRA186_SID_SCE,
792 .id = TEGRA186_MEMORY_CLIENT_SCEW,
794 .sid = TEGRA186_SID_SCE,
802 .id = TEGRA186_MEMORY_CLIENT_SCEDMAR,
804 .sid = TEGRA186_SID_SCE,
812 .id = TEGRA186_MEMORY_CLIENT_SCEDMAW,
814 .sid = TEGRA186_SID_SCE,
822 .id = TEGRA186_MEMORY_CLIENT_APEDMAR,
824 .sid = TEGRA186_SID_APE,
832 .id = TEGRA186_MEMORY_CLIENT_APEDMAW,
834 .sid = TEGRA186_SID_APE,
842 .id = TEGRA186_MEMORY_CLIENT_NVDISPLAYR1,
843 .name = "nvdisplayr1",
844 .sid = TEGRA186_SID_NVDISPLAY,
852 .id = TEGRA186_MEMORY_CLIENT_VICSRD1,
854 .sid = TEGRA186_SID_VIC,
862 .id = TEGRA186_MEMORY_CLIENT_NVDECSRD1,
864 .sid = TEGRA186_SID_NVDEC,
874 const struct tegra_mc_soc tegra186_mc_soc = {
875 .num_clients = ARRAY_SIZE(tegra186_mc_clients),
876 .clients = tegra186_mc_clients,
877 .num_address_bits = 40,
878 .ops = &tegra186_mc_ops,