MC SID and Broadbast channel register access is restricted for Guest VM. In Tegra MC driver, consider both the regions as optional and skip access to restricted registers from Guest if a region is not present in Guest DT. Signed-off-by: Sumit Gupta <sumitg@xxxxxxxxxx> --- drivers/memory/tegra/mc.c | 9 ++++++++- drivers/memory/tegra/mc.h | 18 +++++++++--------- drivers/memory/tegra/tegra186.c | 22 ++++++++++++---------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 224b488794e5..d819dab1b223 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -899,6 +899,7 @@ static void tegra_mc_num_channel_enabled(struct tegra_mc *mc) static int tegra_mc_probe(struct platform_device *pdev) { + struct resource *res; struct tegra_mc *mc; u64 mask; int err; @@ -923,7 +924,13 @@ static int tegra_mc_probe(struct platform_device *pdev) /* length of MC tick in nanoseconds */ mc->tick = 30; - mc->regs = devm_platform_ioremap_resource(pdev, 0); + if (mc->soc->num_channels) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sid"); + if (res) + mc->regs = devm_ioremap_resource(&pdev->dev, res); + } else { + mc->regs = devm_platform_ioremap_resource(pdev, 0); + } if (IS_ERR(mc->regs)) return PTR_ERR(mc->regs); diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index c3f6655bec60..5cdb9451f364 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -112,11 +112,11 @@ icc_provider_to_tegra_mc(struct icc_provider *provider) static inline u32 mc_ch_readl(const struct tegra_mc *mc, int ch, unsigned long offset) { - if (!mc->bcast_ch_regs) - return 0; - - if (ch == MC_BROADCAST_CHANNEL) + if (ch == MC_BROADCAST_CHANNEL) { + if (!mc->bcast_ch_regs) + return 0; return readl_relaxed(mc->bcast_ch_regs + offset); + } return readl_relaxed(mc->ch_regs[ch] + offset); } @@ -124,13 +124,13 @@ static inline u32 mc_ch_readl(const struct tegra_mc *mc, int ch, static inline void mc_ch_writel(const struct tegra_mc *mc, int ch, u32 value, unsigned long offset) { - if (!mc->bcast_ch_regs) - return; - - if (ch == MC_BROADCAST_CHANNEL) + if (ch == MC_BROADCAST_CHANNEL) { + if (!mc->bcast_ch_regs) + return; writel_relaxed(value, mc->bcast_ch_regs + offset); - else + } else { writel_relaxed(value, mc->ch_regs[ch] + offset); + } } static inline u32 mc_readl(const struct tegra_mc *mc, unsigned long offset) diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index 1b3183951bfe..7b5e9bd13ffd 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -26,20 +26,16 @@ static int tegra186_mc_probe(struct tegra_mc *mc) { struct platform_device *pdev = to_platform_device(mc->dev); + struct resource *res; unsigned int i; char name[8]; int err; - mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "broadcast"); - if (IS_ERR(mc->bcast_ch_regs)) { - if (PTR_ERR(mc->bcast_ch_regs) == -EINVAL) { - dev_warn(&pdev->dev, - "Broadcast channel is missing, please update your device-tree\n"); - mc->bcast_ch_regs = NULL; - goto populate; - } - - return PTR_ERR(mc->bcast_ch_regs); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "broadcast"); + if (res) { + mc->bcast_ch_regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mc->bcast_ch_regs)) + return PTR_ERR(mc->bcast_ch_regs); } mc->ch_regs = devm_kcalloc(mc->dev, mc->soc->num_channels, sizeof(*mc->ch_regs), @@ -121,6 +117,9 @@ static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev) if (!tegra_dev_iommu_get_stream_id(dev, &sid)) return 0; + if (!mc->regs) + return 0; + while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells", index, &args)) { if (args.np == mc->dev->of_node && args.args_count != 0) { @@ -146,6 +145,9 @@ static int tegra186_mc_resume(struct tegra_mc *mc) #if IS_ENABLED(CONFIG_IOMMU_API) unsigned int i; + if (!mc->regs) + return 0; + for (i = 0; i < mc->soc->num_clients; i++) { const struct tegra_mc_client *client = &mc->soc->clients[i]; -- 2.17.1