Signed-off-by: Ashish Mhetre <amhetre@xxxxxxxxxx> --- drivers/memory/tegra/mc.c | 6 ++++ drivers/memory/tegra/tegra186.c | 52 +++++++++++++++++++++++++++++++++ drivers/memory/tegra/tegra194.c | 1 + drivers/memory/tegra/tegra234.c | 1 + include/soc/tegra/mc.h | 7 +++++ 5 files changed, 67 insertions(+) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index bf3abb6d8354..3cda1d9ad32a 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -749,6 +749,12 @@ static int tegra_mc_probe(struct platform_device *pdev) if (IS_ERR(mc->regs)) return PTR_ERR(mc->regs); + if (mc->soc->ops && mc->soc->ops->map_regs) { + err = mc->soc->ops->map_regs(mc, pdev); + if (err < 0) + return err; + } + mc->debugfs.root = debugfs_create_dir("mc", NULL); if (mc->soc->ops && mc->soc->ops->probe) { diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index 3d153881abc1..a8a45e6ff1f1 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -139,11 +139,62 @@ static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev) return 0; } +static int tegra186_mc_map_regs(struct tegra_mc *mc, + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.parent->of_node; + int num_dt_channels, reg_cells = 0; + struct resource *res; + int i, ret; + u32 val; + + ret = of_property_read_u32(np, "#address-cells", &val); + if (ret) { + dev_err(&pdev->dev, "missing #address-cells property\n"); + return ret; + } + + reg_cells = val; + + ret = of_property_read_u32(np, "#size-cells", &val); + if (ret) { + dev_err(&pdev->dev, "missing #size-cells property\n"); + return ret; + } + + reg_cells += val; + + num_dt_channels = of_property_count_elems_of_size(pdev->dev.of_node, "reg", + reg_cells * sizeof(u32)); + /* + * On tegra186 onwards, memory controller support multiple channels. + * Apart from regular memory controller channels, there is one broadcast + * channel and one for stream-id registers. + */ + if (num_dt_channels < mc->soc->num_channels + 2) { + dev_warn(&pdev->dev, "MC channels are missing, please update\n"); + return 0; + } + + mc->mcb_regs = devm_platform_get_and_ioremap_resource(pdev, 1, &res); + if (IS_ERR(mc->mcb_regs)) + return PTR_ERR(mc->mcb_regs); + + for (i = 0; i < mc->soc->num_channels; i++) { + mc->mc_regs[i] = devm_platform_get_and_ioremap_resource(pdev, i + 2, &res); + if (IS_ERR(mc->mc_regs[i])) + return PTR_ERR(mc->mc_regs[i]); + } + + return 0; +} + const struct tegra_mc_ops tegra186_mc_ops = { .probe = tegra186_mc_probe, .remove = tegra186_mc_remove, .resume = tegra186_mc_resume, .probe_device = tegra186_mc_probe_device, + .map_regs = tegra186_mc_map_regs, }; #if defined(CONFIG_ARCH_TEGRA_186_SOC) @@ -875,6 +926,7 @@ const struct tegra_mc_soc tegra186_mc_soc = { .num_clients = ARRAY_SIZE(tegra186_mc_clients), .clients = tegra186_mc_clients, .num_address_bits = 40, + .num_channels = 4, .ops = &tegra186_mc_ops, }; #endif diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index cab998b8bd5c..94001174deaf 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1347,5 +1347,6 @@ const struct tegra_mc_soc tegra194_mc_soc = { .num_clients = ARRAY_SIZE(tegra194_mc_clients), .clients = tegra194_mc_clients, .num_address_bits = 40, + .num_channels = 16, .ops = &tegra186_mc_ops, }; diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index e22824a79f45..6335a132be2d 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -97,5 +97,6 @@ const struct tegra_mc_soc tegra234_mc_soc = { .num_clients = ARRAY_SIZE(tegra234_mc_clients), .clients = tegra234_mc_clients, .num_address_bits = 40, + .num_channels = 16, .ops = &tegra186_mc_ops, }; diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 1066b1194a5a..92f810c55b43 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -13,6 +13,9 @@ #include <linux/irq.h> #include <linux/reset-controller.h> #include <linux/types.h> +#include <linux/platform_device.h> + +#define MC_MAX_CHANNELS 16 struct clk; struct device; @@ -181,6 +184,7 @@ struct tegra_mc_ops { int (*resume)(struct tegra_mc *mc); irqreturn_t (*handle_irq)(int irq, void *data); int (*probe_device)(struct tegra_mc *mc, struct device *dev); + int (*map_regs)(struct tegra_mc *mc, struct platform_device *pdev); }; struct tegra_mc_soc { @@ -194,6 +198,7 @@ struct tegra_mc_soc { unsigned int atom_size; u8 client_id_mask; + u8 num_channels; const struct tegra_smmu_soc *smmu; @@ -212,6 +217,8 @@ struct tegra_mc { struct tegra_smmu *smmu; struct gart_device *gart; void __iomem *regs; + void __iomem *mcb_regs; + void __iomem *mc_regs[MC_MAX_CHANNELS]; struct clk *clk; int irq; -- 2.17.1