memory: tegra: Add memory controller channels support
authorAshish Mhetre <amhetre@nvidia.com>
Fri, 6 May 2022 13:23:11 +0000 (15:23 +0200)
committerKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Mon, 9 May 2022 08:46:11 +0000 (10:46 +0200)
From Tegra186 onwards, the memory controller supports multiple channels.
Add support for mapping the address spaces of these channels and specify
the number of channels supported by Tegra186, Tegra194 and Tegra234.

In case of old bindings, channels won't be present. If channels are not
present then print a warning and continue so that backward compatibility
will be preserved in driver.

During error interrupts from memory controller, appropriate registers
from these channels need to be accessed for logging error info.

Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
Reviewed-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://lore.kernel.org/r/20220506132312.3910637-4-thierry.reding@gmail.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
drivers/memory/tegra/tegra186.c
drivers/memory/tegra/tegra194.c
drivers/memory/tegra/tegra234.c
include/soc/tegra/mc.h

index 3d153881abc1668818ac8f4c97af54fc3ef9d63b..4a84752403d817a7b050291f7963fe91a57420e7 100644 (file)
@@ -48,8 +48,37 @@ static void tegra186_mc_program_sid(struct tegra_mc *mc)
 
 static int tegra186_mc_probe(struct tegra_mc *mc)
 {
+       struct platform_device *pdev = to_platform_device(mc->dev);
+       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);
+       }
+
+       mc->ch_regs = devm_kcalloc(mc->dev, mc->soc->num_channels, sizeof(*mc->ch_regs),
+                                  GFP_KERNEL);
+       if (!mc->ch_regs)
+               return -ENOMEM;
+
+       for (i = 0; i < mc->soc->num_channels; i++) {
+               snprintf(name, sizeof(name), "ch%u", i);
+
+               mc->ch_regs[i] = devm_platform_ioremap_resource_byname(pdev, name);
+               if (IS_ERR(mc->ch_regs[i]))
+                       return PTR_ERR(mc->ch_regs[i]);
+       }
+
+populate:
        err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
        if (err < 0)
                return err;
@@ -875,6 +904,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
index cab998b8bd5ca6fc25e8007347a8c4e7a8656476..94001174deaf2b5b4ed5ec7e12aa8c94c5014a02 100644 (file)
@@ -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,
 };
index e22824a79f4591cfc057a114292b6aa1890da297..6335a132be2d5841951311aa23d392eda6cb38d7 100644 (file)
@@ -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,
 };
index 1066b1194a5a9ac4a5fdcad1c170141bc2969f80..40f1d02a135894ca86ace21d31ed9c6ef199eac8 100644 (file)
@@ -194,6 +194,7 @@ struct tegra_mc_soc {
        unsigned int atom_size;
 
        u8 client_id_mask;
+       u8 num_channels;
 
        const struct tegra_smmu_soc *smmu;
 
@@ -212,6 +213,8 @@ struct tegra_mc {
        struct tegra_smmu *smmu;
        struct gart_device *gart;
        void __iomem *regs;
+       void __iomem *bcast_ch_regs;
+       void __iomem **ch_regs;
        struct clk *clk;
        int irq;