mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
Move init function from OF_DECLARE() argument to the given reserved memory region ops structure and then pass that structure to the OF_DECLARE() initializer. This node_init callback is mandatory for the reserved mem driver. Such change makes it possible in the future to add more functions called by the generic code before given memory region is initialized and rmem object is created. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Link: https://patch.msgid.link/20260325090023.3175348-4-m.szyprowski@samsung.com Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
90 lines
2.1 KiB
C
90 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/of_reserved_mem.h>
|
|
|
|
#include "tegra210-emc.h"
|
|
|
|
#define TEGRA_EMC_MAX_FREQS 16
|
|
|
|
static int tegra210_emc_table_device_init(struct reserved_mem *rmem,
|
|
struct device *dev)
|
|
{
|
|
struct tegra210_emc *emc = dev_get_drvdata(dev);
|
|
struct tegra210_emc_timing *timings;
|
|
unsigned int i, count = 0;
|
|
|
|
timings = memremap(rmem->base, rmem->size, MEMREMAP_WB);
|
|
if (!timings) {
|
|
dev_err(dev, "failed to map EMC table\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
for (i = 0; i < TEGRA_EMC_MAX_FREQS; i++) {
|
|
if (timings[i].revision == 0)
|
|
break;
|
|
|
|
count++;
|
|
}
|
|
|
|
/* only the nominal and derated tables are expected */
|
|
if (emc->derated) {
|
|
dev_warn(dev, "excess EMC table '%s'\n", rmem->name);
|
|
goto out;
|
|
}
|
|
|
|
if (emc->nominal) {
|
|
if (count != emc->num_timings) {
|
|
dev_warn(dev, "%u derated vs. %u nominal entries\n",
|
|
count, emc->num_timings);
|
|
memunmap(timings);
|
|
return -EINVAL;
|
|
}
|
|
|
|
emc->derated = timings;
|
|
} else {
|
|
emc->num_timings = count;
|
|
emc->nominal = timings;
|
|
}
|
|
|
|
out:
|
|
/* keep track of which table this is */
|
|
rmem->priv = timings;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void tegra210_emc_table_device_release(struct reserved_mem *rmem,
|
|
struct device *dev)
|
|
{
|
|
struct tegra210_emc_timing *timings = rmem->priv;
|
|
struct tegra210_emc *emc = dev_get_drvdata(dev);
|
|
|
|
if ((emc->nominal && timings != emc->nominal) &&
|
|
(emc->derated && timings != emc->derated))
|
|
dev_warn(dev, "trying to release unassigned EMC table '%s'\n",
|
|
rmem->name);
|
|
|
|
memunmap(timings);
|
|
}
|
|
|
|
static int tegra210_emc_table_init(unsigned long node,
|
|
struct reserved_mem *rmem)
|
|
{
|
|
pr_debug("Tegra210 EMC table at %pa, size %lu bytes\n", &rmem->base,
|
|
(unsigned long)rmem->size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct reserved_mem_ops tegra210_emc_table_ops = {
|
|
.node_init = tegra210_emc_table_init,
|
|
.device_init = tegra210_emc_table_device_init,
|
|
.device_release = tegra210_emc_table_device_release,
|
|
};
|
|
|
|
RESERVEDMEM_OF_DECLARE(tegra210_emc_table, "nvidia,tegra210-emc-table",
|
|
&tegra210_emc_table_ops);
|