summaryrefslogtreecommitdiff
path: root/drivers/memory
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-05-26 10:32:47 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-05-26 10:32:47 -0700
commitcc3c470ae4ad758b8ddad825ab199f7eaa8b0a9e (patch)
tree779e3dc27a1f4d1468bad2ea5cbfca28c64cf1cd /drivers/memory
parentae862183285cbb2ef9032770d98ffa9becffe9d5 (diff)
parentd4a3b442335b0a9476248c5d6dc07f6f8580a9ca (diff)
Merge tag 'arm-drivers-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM driver updates from Arnd Bergmann: "There are minor updates to SoC specific drivers for chips by Rockchip, Samsung, NVIDIA, TI, NXP, i.MX, Qualcomm, and Broadcom. Noteworthy driver changes include: - Several conversions of DT bindings to yaml format. - Renesas adds driver support for R-Car V4H, RZ/V2M and RZ/G2UL SoCs. - Qualcomm adds a bus driver for the SSC (Snapdragon Sensor Core), and support for more chips in the RPMh power domains and the soc-id. - NXP has a new driver for the HDMI blk-ctrl on i.MX8MP. - Apple M1 gains support for the on-chip NVMe controller, making it possible to finally use the internal disks. This also includes SoC drivers for their RTKit IPC and for the SART DMA address filter. For other subsystems that merge their drivers through the SoC tree, we have - Firmware drivers for the ARM firmware stack including TEE, OP-TEE, SCMI and FF-A get a number of smaller updates and cleanups. OP-TEE now has a cache for firmware argument structures as an optimization, and SCMI now supports the 3.1 version of the specification. - Reset controller updates to Amlogic, ASpeed, Renesas and ACPI drivers - Memory controller updates for Tegra, and a few updates for other platforms" * tag 'arm-drivers-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (159 commits) memory: tegra: Add MC error logging on Tegra186 onward memory: tegra: Add memory controller channels support memory: tegra: Add APE memory clients for Tegra234 memory: tegra: Add Tegra234 support nvme-apple: fix sparse endianess warnings soc/tegra: pmc: Document core domain fields soc: qcom: pdr: use static for servreg_* variables soc: imx: fix semicolon.cocci warnings soc: renesas: R-Car V3U is R-Car Gen4 soc: imx: add i.MX8MP HDMI blk-ctrl soc: imx: imx8m-blk-ctrl: Add i.MX8MP media blk-ctrl soc: imx: add i.MX8MP HSIO blk-ctrl soc: imx: imx8m-blk-ctrl: set power device name soc: qcom: llcc: Add sc8180x and sc8280xp configurations dt-bindings: arm: msm: Add sc8180x and sc8280xp LLCC compatibles soc/tegra: pmc: Select REGMAP dt-bindings: reset: st,sti-powerdown: Convert to yaml dt-bindings: reset: st,sti-picophyreset: Convert to yaml dt-bindings: reset: socfpga: Convert to yaml dt-bindings: reset: snps,axs10x-reset: Convert to yaml ...
Diffstat (limited to 'drivers/memory')
-rw-r--r--drivers/memory/Kconfig2
-rw-r--r--drivers/memory/brcmstb_dpfe.c10
-rw-r--r--drivers/memory/da8xx-ddrctl.c3
-rw-r--r--drivers/memory/emif.c15
-rw-r--r--drivers/memory/fsl-corenet-cf.c9
-rw-r--r--drivers/memory/omap-gpmc.c43
-rw-r--r--drivers/memory/renesas-rpc-if.c31
-rw-r--r--drivers/memory/samsung/exynos5422-dmc.c5
-rw-r--r--drivers/memory/tegra/Makefile2
-rw-r--r--drivers/memory/tegra/mc.c141
-rw-r--r--drivers/memory/tegra/mc.h50
-rw-r--r--drivers/memory/tegra/tegra186-emc.c3
-rw-r--r--drivers/memory/tegra/tegra186.c39
-rw-r--r--drivers/memory/tegra/tegra194.c9
-rw-r--r--drivers/memory/tegra/tegra234.c110
-rw-r--r--drivers/memory/ti-aemif.c4
-rw-r--r--drivers/memory/ti-emif-pm.c6
17 files changed, 379 insertions, 103 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 30bff6cb1b8d..b7800b37af78 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -103,7 +103,7 @@ config TI_EMIF
temperature changes
config OMAP_GPMC
- bool "Texas Instruments OMAP SoC GPMC driver" if COMPILE_TEST
+ tristate "Texas Instruments OMAP SoC GPMC driver"
depends on OF_ADDRESS
select GPIOLIB
help
diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c
index 14412002775d..76c82e9c8fce 100644
--- a/drivers/memory/brcmstb_dpfe.c
+++ b/drivers/memory/brcmstb_dpfe.c
@@ -857,7 +857,6 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct brcmstb_dpfe_priv *priv;
- struct resource *res;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -869,22 +868,19 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
mutex_init(&priv->lock);
platform_set_drvdata(pdev, priv);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-cpu");
- priv->regs = devm_ioremap_resource(dev, res);
+ priv->regs = devm_platform_ioremap_resource_byname(pdev, "dpfe-cpu");
if (IS_ERR(priv->regs)) {
dev_err(dev, "couldn't map DCPU registers\n");
return -ENODEV;
}
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-dmem");
- priv->dmem = devm_ioremap_resource(dev, res);
+ priv->dmem = devm_platform_ioremap_resource_byname(pdev, "dpfe-dmem");
if (IS_ERR(priv->dmem)) {
dev_err(dev, "Couldn't map DCPU data memory\n");
return -ENOENT;
}
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-imem");
- priv->imem = devm_ioremap_resource(dev, res);
+ priv->imem = devm_platform_ioremap_resource_byname(pdev, "dpfe-imem");
if (IS_ERR(priv->imem)) {
dev_err(dev, "Couldn't map DCPU instruction memory\n");
return -ENOENT;
diff --git a/drivers/memory/da8xx-ddrctl.c b/drivers/memory/da8xx-ddrctl.c
index 872addd0ec60..b32005bf269c 100644
--- a/drivers/memory/da8xx-ddrctl.c
+++ b/drivers/memory/da8xx-ddrctl.c
@@ -115,8 +115,7 @@ static int da8xx_ddrctl_probe(struct platform_device *pdev)
return -EINVAL;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ddrctl = devm_ioremap_resource(dev, res);
+ ddrctl = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(ddrctl)) {
dev_err(dev, "unable to map memory controller registers\n");
return PTR_ERR(ddrctl);
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index ecc78d6f89ed..6c2a421b86e3 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -1025,10 +1025,8 @@ static struct emif_data *__init_or_module get_device_details(
temp = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL);
- if (!emif || !temp || !dev_info) {
- dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__);
+ if (!emif || !temp || !dev_info)
goto error;
- }
memcpy(temp, pd, sizeof(*pd));
pd = temp;
@@ -1067,9 +1065,6 @@ static struct emif_data *__init_or_module get_device_details(
temp = devm_kzalloc(dev, sizeof(*cust_cfgs), GFP_KERNEL);
if (temp)
memcpy(temp, cust_cfgs, sizeof(*cust_cfgs));
- else
- dev_warn(dev, "%s:%d: allocation error\n", __func__,
- __LINE__);
pd->custom_configs = temp;
}
@@ -1084,8 +1079,6 @@ static struct emif_data *__init_or_module get_device_details(
memcpy(temp, pd->timings, size);
pd->timings = temp;
} else {
- dev_warn(dev, "%s:%d: allocation error\n", __func__,
- __LINE__);
get_default_timings(emif);
}
} else {
@@ -1098,8 +1091,6 @@ static struct emif_data *__init_or_module get_device_details(
memcpy(temp, pd->min_tck, sizeof(*pd->min_tck));
pd->min_tck = temp;
} else {
- dev_warn(dev, "%s:%d: allocation error\n", __func__,
- __LINE__);
pd->min_tck = &lpddr2_jedec_min_tck;
}
} else {
@@ -1116,7 +1107,6 @@ error:
static int __init_or_module emif_probe(struct platform_device *pdev)
{
struct emif_data *emif;
- struct resource *res;
int irq, ret;
if (pdev->dev.of_node)
@@ -1135,8 +1125,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
emif->dev = &pdev->dev;
platform_set_drvdata(pdev, emif);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- emif->base = devm_ioremap_resource(emif->dev, res);
+ emif->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(emif->base))
goto error;
diff --git a/drivers/memory/fsl-corenet-cf.c b/drivers/memory/fsl-corenet-cf.c
index f8ea592c9cb5..7fc9f57ae278 100644
--- a/drivers/memory/fsl-corenet-cf.c
+++ b/drivers/memory/fsl-corenet-cf.c
@@ -172,7 +172,6 @@ out:
static int ccf_probe(struct platform_device *pdev)
{
struct ccf_private *ccf;
- struct resource *r;
const struct of_device_id *match;
u32 errinten;
int ret, irq;
@@ -185,13 +184,7 @@ static int ccf_probe(struct platform_device *pdev)
if (!ccf)
return -ENOMEM;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
- return -ENXIO;
- }
-
- ccf->regs = devm_ioremap_resource(&pdev->dev, r);
+ ccf->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ccf->regs))
return PTR_ERR(ccf->regs);
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index ed11887c1b7c..2351f2708da2 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -12,6 +12,7 @@
#include <linux/cpu_pm.h>
#include <linux/irq.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -1889,16 +1890,6 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
}
#ifdef CONFIG_OF
-static const struct of_device_id gpmc_dt_ids[] = {
- { .compatible = "ti,omap2420-gpmc" },
- { .compatible = "ti,omap2430-gpmc" },
- { .compatible = "ti,omap3430-gpmc" }, /* omap3430 & omap3630 */
- { .compatible = "ti,omap4430-gpmc" }, /* omap4430 & omap4460 & omap543x */
- { .compatible = "ti,am3352-gpmc" }, /* am335x devices */
- { .compatible = "ti,am64-gpmc" },
- { }
-};
-
static void gpmc_cs_set_name(int cs, const char *name)
{
struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
@@ -2257,11 +2248,9 @@ no_timings:
if (!of_platform_device_create(child, NULL, &pdev->dev))
goto err_child_fail;
- /* is child a common bus? */
- if (of_match_node(of_default_bus_match_table, child))
- /* create children and other common bus children */
- if (of_platform_default_populate(child, NULL, &pdev->dev))
- goto err_child_fail;
+ /* create children and other common bus children */
+ if (of_platform_default_populate(child, NULL, &pdev->dev))
+ goto err_child_fail;
return 0;
@@ -2278,6 +2267,8 @@ err:
return ret;
}
+static const struct of_device_id gpmc_dt_ids[];
+
static int gpmc_probe_dt(struct platform_device *pdev)
{
int ret;
@@ -2644,6 +2635,19 @@ static int gpmc_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(gpmc_pm_ops, gpmc_suspend, gpmc_resume);
+#ifdef CONFIG_OF
+static const struct of_device_id gpmc_dt_ids[] = {
+ { .compatible = "ti,omap2420-gpmc" },
+ { .compatible = "ti,omap2430-gpmc" },
+ { .compatible = "ti,omap3430-gpmc" }, /* omap3430 & omap3630 */
+ { .compatible = "ti,omap4430-gpmc" }, /* omap4430 & omap4460 & omap543x */
+ { .compatible = "ti,am3352-gpmc" }, /* am335x devices */
+ { .compatible = "ti,am64-gpmc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
+#endif
+
static struct platform_driver gpmc_driver = {
.probe = gpmc_probe,
.remove = gpmc_remove,
@@ -2654,8 +2658,7 @@ static struct platform_driver gpmc_driver = {
},
};
-static __init int gpmc_init(void)
-{
- return platform_driver_register(&gpmc_driver);
-}
-postcore_initcall(gpmc_init);
+module_platform_driver(gpmc_driver);
+
+MODULE_DESCRIPTION("Texas Instruments GPMC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
index 019a0822bde0..4316988d791a 100644
--- a/drivers/memory/renesas-rpc-if.c
+++ b/drivers/memory/renesas-rpc-if.c
@@ -259,8 +259,7 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
rpc->dev = dev;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- rpc->base = devm_ioremap_resource(&pdev->dev, res);
+ rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs");
if (IS_ERR(rpc->base))
return PTR_ERR(rpc->base);
@@ -488,7 +487,7 @@ int rpcif_manual_xfer(struct rpcif *rpc)
case RPCIF_DATA_OUT:
while (pos < rpc->xferlen) {
u32 bytes_left = rpc->xferlen - pos;
- u32 nbytes, data[2];
+ u32 nbytes, data[2], *p = data;
smcr = rpc->smcr | RPCIF_SMCR_SPIE;
@@ -502,15 +501,9 @@ int rpcif_manual_xfer(struct rpcif *rpc)
rpc->xfer_size = nbytes;
memcpy(data, rpc->buffer + pos, nbytes);
- if (nbytes == 8) {
- regmap_write(rpc->regmap, RPCIF_SMWDR1,
- data[0]);
- regmap_write(rpc->regmap, RPCIF_SMWDR0,
- data[1]);
- } else {
- regmap_write(rpc->regmap, RPCIF_SMWDR0,
- data[0]);
- }
+ if (nbytes == 8)
+ regmap_write(rpc->regmap, RPCIF_SMWDR1, *p++);
+ regmap_write(rpc->regmap, RPCIF_SMWDR0, *p);
regmap_write(rpc->regmap, RPCIF_SMCR, smcr);
ret = wait_msg_xfer_end(rpc);
@@ -552,7 +545,7 @@ int rpcif_manual_xfer(struct rpcif *rpc)
}
while (pos < rpc->xferlen) {
u32 bytes_left = rpc->xferlen - pos;
- u32 nbytes, data[2];
+ u32 nbytes, data[2], *p = data;
/* nbytes may only be 1, 2, 4, or 8 */
nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left));
@@ -569,15 +562,9 @@ int rpcif_manual_xfer(struct rpcif *rpc)
if (ret)
goto err_out;
- if (nbytes == 8) {
- regmap_read(rpc->regmap, RPCIF_SMRDR1,
- &data[0]);
- regmap_read(rpc->regmap, RPCIF_SMRDR0,
- &data[1]);
- } else {
- regmap_read(rpc->regmap, RPCIF_SMRDR0,
- &data[0]);
- }
+ if (nbytes == 8)
+ regmap_read(rpc->regmap, RPCIF_SMRDR1, p++);
+ regmap_read(rpc->regmap, RPCIF_SMRDR0, p);
memcpy(rpc->buffer + pos, data, nbytes);
pos += nbytes;
diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c
index 9c8318923ed0..4733e7898ffe 100644
--- a/drivers/memory/samsung/exynos5422-dmc.c
+++ b/drivers/memory/samsung/exynos5422-dmc.c
@@ -1322,7 +1322,6 @@ static int exynos5_dmc_init_clks(struct exynos5_dmc *dmc)
*/
static int exynos5_performance_counters_init(struct exynos5_dmc *dmc)
{
- int counters_size;
int ret, i;
dmc->num_counters = devfreq_event_get_edev_count(dmc->dev,
@@ -1332,8 +1331,8 @@ static int exynos5_performance_counters_init(struct exynos5_dmc *dmc)
return dmc->num_counters;
}
- counters_size = sizeof(struct devfreq_event_dev) * dmc->num_counters;
- dmc->counter = devm_kzalloc(dmc->dev, counters_size, GFP_KERNEL);
+ dmc->counter = devm_kcalloc(dmc->dev, dmc->num_counters,
+ sizeof(*dmc->counter), GFP_KERNEL);
if (!dmc->counter)
return -ENOMEM;
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
index c992e87782d2..0750847dac3c 100644
--- a/drivers/memory/tegra/Makefile
+++ b/drivers/memory/tegra/Makefile
@@ -9,6 +9,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra124.o
tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
tegra-mc-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o
tegra-mc-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186.o tegra194.o
+tegra-mc-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186.o tegra234.o
obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
@@ -19,5 +20,6 @@ obj-$(CONFIG_TEGRA210_EMC_TABLE) += tegra210-emc-table.o
obj-$(CONFIG_TEGRA210_EMC) += tegra210-emc.o
obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-emc.o
obj-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra186-emc.o
+obj-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra186-emc.o
tegra210-emc-y := tegra210-emc-core.o tegra210-emc-cc-r21021.o
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index 44b4a4080920..2f7a58a9df1a 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -45,6 +45,9 @@ static const struct of_device_id tegra_mc_of_match[] = {
#ifdef CONFIG_ARCH_TEGRA_194_SOC
{ .compatible = "nvidia,tegra194-mc", .data = &tegra194_mc_soc },
#endif
+#ifdef CONFIG_ARCH_TEGRA_234_SOC
+ { .compatible = "nvidia,tegra234-mc", .data = &tegra234_mc_soc },
+#endif
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
@@ -505,14 +508,54 @@ int tegra30_mc_probe(struct tegra_mc *mc)
return 0;
}
-static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
+const struct tegra_mc_ops tegra30_mc_ops = {
+ .probe = tegra30_mc_probe,
+ .handle_irq = tegra30_mc_handle_irq,
+};
+#endif
+
+static int mc_global_intstatus_to_channel(const struct tegra_mc *mc, u32 status,
+ unsigned int *mc_channel)
+{
+ if ((status & mc->soc->ch_intmask) == 0)
+ return -EINVAL;
+
+ *mc_channel = __ffs((status & mc->soc->ch_intmask) >>
+ mc->soc->global_intstatus_channel_shift);
+
+ return 0;
+}
+
+static u32 mc_channel_to_global_intstatus(const struct tegra_mc *mc,
+ unsigned int channel)
+{
+ return BIT(channel) << mc->soc->global_intstatus_channel_shift;
+}
+
+irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
{
struct tegra_mc *mc = data;
+ unsigned int bit, channel;
unsigned long status;
- unsigned int bit;
- /* mask all interrupts to avoid flooding */
- status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
+ if (mc->soc->num_channels) {
+ u32 global_status;
+ int err;
+
+ global_status = mc_ch_readl(mc, MC_BROADCAST_CHANNEL, MC_GLOBAL_INTSTATUS);
+ err = mc_global_intstatus_to_channel(mc, global_status, &channel);
+ if (err < 0) {
+ dev_err_ratelimited(mc->dev, "unknown interrupt channel 0x%08x\n",
+ global_status);
+ return IRQ_NONE;
+ }
+
+ /* mask all interrupts to avoid flooding */
+ status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmask;
+ } else {
+ status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
+ }
+
if (!status)
return IRQ_NONE;
@@ -520,18 +563,70 @@ static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
const char *error = tegra_mc_status_names[bit] ?: "unknown";
const char *client = "unknown", *desc;
const char *direction, *secure;
+ u32 status_reg, addr_reg;
+ u32 intmask = BIT(bit);
phys_addr_t addr = 0;
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+ u32 addr_hi_reg = 0;
+#endif
unsigned int i;
char perm[7];
u8 id, type;
u32 value;
- value = mc_readl(mc, MC_ERR_STATUS);
+ switch (intmask) {
+ case MC_INT_DECERR_VPR:
+ status_reg = MC_ERR_VPR_STATUS;
+ addr_reg = MC_ERR_VPR_ADR;
+ break;
+
+ case MC_INT_SECERR_SEC:
+ status_reg = MC_ERR_SEC_STATUS;
+ addr_reg = MC_ERR_SEC_ADR;
+ break;
+
+ case MC_INT_DECERR_MTS:
+ status_reg = MC_ERR_MTS_STATUS;
+ addr_reg = MC_ERR_MTS_ADR;
+ break;
+
+ case MC_INT_DECERR_GENERALIZED_CARVEOUT:
+ status_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS;
+ addr_reg = MC_ERR_GENERALIZED_CARVEOUT_ADR;
+ break;
+
+ case MC_INT_DECERR_ROUTE_SANITY:
+ status_reg = MC_ERR_ROUTE_SANITY_STATUS;
+ addr_reg = MC_ERR_ROUTE_SANITY_ADR;
+ break;
+
+ default:
+ status_reg = MC_ERR_STATUS;
+ addr_reg = MC_ERR_ADR;
+
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+ if (mc->soc->has_addr_hi_reg)
+ addr_hi_reg = MC_ERR_ADR_HI;
+#endif
+ break;
+ }
+
+ if (mc->soc->num_channels)
+ value = mc_ch_readl(mc, channel, status_reg);
+ else
+ value = mc_readl(mc, status_reg);
#ifdef CONFIG_PHYS_ADDR_T_64BIT
if (mc->soc->num_address_bits > 32) {
- addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) &
- MC_ERR_STATUS_ADR_HI_MASK);
+ if (addr_hi_reg) {
+ if (mc->soc->num_channels)
+ addr = mc_ch_readl(mc, channel, addr_hi_reg);
+ else
+ addr = mc_readl(mc, addr_hi_reg);
+ } else {
+ addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) &
+ MC_ERR_STATUS_ADR_HI_MASK);
+ }
addr <<= 32;
}
#endif
@@ -588,7 +683,10 @@ static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
break;
}
- value = mc_readl(mc, MC_ERR_ADR);
+ if (mc->soc->num_channels)
+ value = mc_ch_readl(mc, channel, addr_reg);
+ else
+ value = mc_readl(mc, addr_reg);
addr |= value;
dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s%s)\n",
@@ -597,17 +695,18 @@ static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
}
/* clear interrupts */
- mc_writel(mc, status, MC_INTSTATUS);
+ if (mc->soc->num_channels) {
+ mc_ch_writel(mc, channel, status, MC_INTSTATUS);
+ mc_ch_writel(mc, MC_BROADCAST_CHANNEL,
+ mc_channel_to_global_intstatus(mc, channel),
+ MC_GLOBAL_INTSTATUS);
+ } else {
+ mc_writel(mc, status, MC_INTSTATUS);
+ }
return IRQ_HANDLED;
}
-const struct tegra_mc_ops tegra30_mc_ops = {
- .probe = tegra30_mc_probe,
- .handle_irq = tegra30_mc_handle_irq,
-};
-#endif
-
const char *const tegra_mc_status_names[32] = {
[ 1] = "External interrupt",
[ 6] = "EMEM address decode error",
@@ -619,6 +718,8 @@ const char *const tegra_mc_status_names[32] = {
[12] = "VPR violation",
[13] = "Secure carveout violation",
[16] = "MTS carveout violation",
+ [17] = "Generalized carveout violation",
+ [20] = "Route Sanity error",
};
const char *const tegra_mc_error_names[8] = {
@@ -716,7 +817,6 @@ del_provider:
static int tegra_mc_probe(struct platform_device *pdev)
{
- struct resource *res;
struct tegra_mc *mc;
u64 mask;
int err;
@@ -741,8 +841,7 @@ static int tegra_mc_probe(struct platform_device *pdev)
/* length of MC tick in nanoseconds */
mc->tick = 30;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mc->regs = devm_ioremap_resource(&pdev->dev, res);
+ mc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mc->regs))
return PTR_ERR(mc->regs);
@@ -761,7 +860,11 @@ static int tegra_mc_probe(struct platform_device *pdev)
WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n");
- mc_writel(mc, mc->soc->intmask, MC_INTMASK);
+ if (mc->soc->num_channels)
+ mc_ch_writel(mc, MC_BROADCAST_CHANNEL, mc->soc->intmask,
+ MC_INTMASK);
+ else
+ mc_writel(mc, mc->soc->intmask, MC_INTMASK);
err = devm_request_irq(&pdev->dev, mc->irq, mc->soc->ops->handle_irq, 0,
dev_name(&pdev->dev), mc);
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index 1e492989c363..bc01586b6560 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -43,7 +43,21 @@
#define MC_EMEM_ARB_OVERRIDE 0xe8
#define MC_TIMING_CONTROL_DBG 0xf8
#define MC_TIMING_CONTROL 0xfc
-
+#define MC_ERR_VPR_STATUS 0x654
+#define MC_ERR_VPR_ADR 0x658
+#define MC_ERR_SEC_STATUS 0x67c
+#define MC_ERR_SEC_ADR 0x680
+#define MC_ERR_MTS_STATUS 0x9b0
+#define MC_ERR_MTS_ADR 0x9b4
+#define MC_ERR_ROUTE_SANITY_STATUS 0x9c0
+#define MC_ERR_ROUTE_SANITY_ADR 0x9c4
+#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
+#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
+#define MC_GLOBAL_INTSTATUS 0xf24
+#define MC_ERR_ADR_HI 0x11fc
+
+#define MC_INT_DECERR_ROUTE_SANITY BIT(20)
+#define MC_INT_DECERR_GENERALIZED_CARVEOUT BIT(17)
#define MC_INT_DECERR_MTS BIT(16)
#define MC_INT_SECERR_SEC BIT(13)
#define MC_INT_DECERR_VPR BIT(12)
@@ -78,6 +92,8 @@
#define MC_TIMING_UPDATE BIT(0)
+#define MC_BROADCAST_CHANNEL ~0
+
static inline u32 tegra_mc_scale_percents(u64 val, unsigned int percents)
{
val = val * percents;
@@ -92,6 +108,30 @@ icc_provider_to_tegra_mc(struct icc_provider *provider)
return container_of(provider, struct tegra_mc, 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)
+ return readl_relaxed(mc->bcast_ch_regs + offset);
+
+ return readl_relaxed(mc->ch_regs[ch] + offset);
+}
+
+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)
+ writel_relaxed(value, mc->bcast_ch_regs + offset);
+ else
+ writel_relaxed(value, mc->ch_regs[ch] + offset);
+}
+
static inline u32 mc_readl(const struct tegra_mc *mc, unsigned long offset)
{
return readl_relaxed(mc->regs + offset);
@@ -137,6 +177,10 @@ extern const struct tegra_mc_soc tegra186_mc_soc;
extern const struct tegra_mc_soc tegra194_mc_soc;
#endif
+#ifdef CONFIG_ARCH_TEGRA_234_SOC
+extern const struct tegra_mc_soc tegra234_mc_soc;
+#endif
+
#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
defined(CONFIG_ARCH_TEGRA_114_SOC) || \
defined(CONFIG_ARCH_TEGRA_124_SOC) || \
@@ -147,10 +191,12 @@ extern const struct tegra_mc_ops tegra30_mc_ops;
#endif
#if defined(CONFIG_ARCH_TEGRA_186_SOC) || \
- defined(CONFIG_ARCH_TEGRA_194_SOC)
+ defined(CONFIG_ARCH_TEGRA_194_SOC) || \
+ defined(CONFIG_ARCH_TEGRA_234_SOC)
extern const struct tegra_mc_ops tegra186_mc_ops;
#endif
+irqreturn_t tegra30_mc_handle_irq(int irq, void *data);
extern const char * const tegra_mc_status_names[32];
extern const char * const tegra_mc_error_names[8];
diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c
index 746c4ef2c0af..54b47ca33483 100644
--- a/drivers/memory/tegra/tegra186-emc.c
+++ b/drivers/memory/tegra/tegra186-emc.c
@@ -273,6 +273,9 @@ static const struct of_device_id tegra186_emc_of_match[] = {
#if defined(CONFIG_ARCH_TEGRA_194_SOC)
{ .compatible = "nvidia,tegra194-emc" },
#endif
+#if defined(CONFIG_ARCH_TEGRA_234_SOC)
+ { .compatible = "nvidia,tegra234-emc" },
+#endif
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, tegra186_emc_of_match);
diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
index 3d153881abc1..62477e592bf5 100644
--- a/drivers/memory/tegra/tegra186.c
+++ b/drivers/memory/tegra/tegra186.c
@@ -16,6 +16,8 @@
#include <dt-bindings/memory/tegra186-mc.h>
#endif
+#include "mc.h"
+
#define MC_SID_STREAMID_OVERRIDE_MASK GENMASK(7, 0)
#define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
#define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
@@ -48,8 +50,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;
@@ -144,6 +175,7 @@ const struct tegra_mc_ops tegra186_mc_ops = {
.remove = tegra186_mc_remove,
.resume = tegra186_mc_resume,
.probe_device = tegra186_mc_probe_device,
+ .handle_irq = tegra30_mc_handle_irq,
};
#if defined(CONFIG_ARCH_TEGRA_186_SOC)
@@ -875,6 +907,13 @@ 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,
+ .client_id_mask = 0xff,
+ .intmask = MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
+ MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
+ MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
.ops = &tegra186_mc_ops,
+ .ch_intmask = 0x0000000f,
+ .global_intstatus_channel_shift = 0,
};
#endif
diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c
index cab998b8bd5c..b2416ee3ac26 100644
--- a/drivers/memory/tegra/tegra194.c
+++ b/drivers/memory/tegra/tegra194.c
@@ -1347,5 +1347,14 @@ 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,
+ .client_id_mask = 0xff,
+ .intmask = MC_INT_DECERR_ROUTE_SANITY |
+ MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
+ MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
+ MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
+ .has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
+ .ch_intmask = 0x00000f00,
+ .global_intstatus_channel_shift = 8,
};
diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c
new file mode 100644
index 000000000000..e23ebd421f17
--- /dev/null
+++ b/drivers/memory/tegra/tegra234.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021-2022, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <soc/tegra/mc.h>
+
+#include <dt-bindings/memory/tegra234-mc.h>
+
+#include "mc.h"
+
+static const struct tegra_mc_client tegra234_mc_clients[] = {
+ {
+ .id = TEGRA234_MEMORY_CLIENT_SDMMCRAB,
+ .name = "sdmmcrab",
+ .sid = TEGRA234_SID_SDMMC4,
+ .regs = {
+ .sid = {
+ .override = 0x318,
+ .security = 0x31c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_SDMMCWAB,
+ .name = "sdmmcwab",
+ .sid = TEGRA234_SID_SDMMC4,
+ .regs = {
+ .sid = {
+ .override = 0x338,
+ .security = 0x33c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_BPMPR,
+ .name = "bpmpr",
+ .sid = TEGRA234_SID_BPMP,
+ .regs = {
+ .sid = {
+ .override = 0x498,
+ .security = 0x49c,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_BPMPW,
+ .name = "bpmpw",
+ .sid = TEGRA234_SID_BPMP,
+ .regs = {
+ .sid = {
+ .override = 0x4a0,
+ .security = 0x4a4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_BPMPDMAR,
+ .name = "bpmpdmar",
+ .sid = TEGRA234_SID_BPMP,
+ .regs = {
+ .sid = {
+ .override = 0x4a8,
+ .security = 0x4ac,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_BPMPDMAW,
+ .name = "bpmpdmaw",
+ .sid = TEGRA234_SID_BPMP,
+ .regs = {
+ .sid = {
+ .override = 0x4b0,
+ .security = 0x4b4,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_APEDMAR,
+ .name = "apedmar",
+ .sid = TEGRA234_SID_APE,
+ .regs = {
+ .sid = {
+ .override = 0x4f8,
+ .security = 0x4fc,
+ },
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_APEDMAW,
+ .name = "apedmaw",
+ .sid = TEGRA234_SID_APE,
+ .regs = {
+ .sid = {
+ .override = 0x500,
+ .security = 0x504,
+ },
+ },
+ },
+};
+
+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,
+ .client_id_mask = 0x1ff,
+ .intmask = MC_INT_DECERR_ROUTE_SANITY |
+ MC_INT_DECERR_GENERALIZED_CARVEOUT | MC_INT_DECERR_MTS |
+ MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
+ MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
+ .has_addr_hi_reg = true,
+ .ops = &tegra186_mc_ops,
+ .ch_intmask = 0x0000ff00,
+ .global_intstatus_channel_shift = 8,
+};
diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
index 51d20c2ccb75..f81e7df8798a 100644
--- a/drivers/memory/ti-aemif.c
+++ b/drivers/memory/ti-aemif.c
@@ -328,7 +328,6 @@ static int aemif_probe(struct platform_device *pdev)
{
int i;
int ret = -ENODEV;
- struct resource *res;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct device_node *child_np;
@@ -362,8 +361,7 @@ static int aemif_probe(struct platform_device *pdev)
else if (pdata)
aemif->cs_offset = pdata->cs_offset;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- aemif->base = devm_ioremap_resource(dev, res);
+ aemif->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(aemif->base)) {
ret = PTR_ERR(aemif->base);
goto error;
diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c
index 179fec2da56d..31d6266f008c 100644
--- a/drivers/memory/ti-emif-pm.c
+++ b/drivers/memory/ti-emif-pm.c
@@ -290,9 +290,9 @@ static int ti_emif_probe(struct platform_device *pdev)
emif_data->pm_data.ti_emif_sram_config = (unsigned long)match->data;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- emif_data->pm_data.ti_emif_base_addr_virt = devm_ioremap_resource(dev,
- res);
+ emif_data->pm_data.ti_emif_base_addr_virt = devm_platform_get_and_ioremap_resource(pdev,
+ 0,
+ &res);
if (IS_ERR(emif_data->pm_data.ti_emif_base_addr_virt)) {
ret = PTR_ERR(emif_data->pm_data.ti_emif_base_addr_virt);
return ret;