110de2114SJoseph Lo // SPDX-License-Identifier: GPL-2.0
210de2114SJoseph Lo /*
310de2114SJoseph Lo  * Copyright (c) 2020, NVIDIA CORPORATION.  All rights reserved.
410de2114SJoseph Lo  */
510de2114SJoseph Lo 
610de2114SJoseph Lo #include <linux/of_reserved_mem.h>
710de2114SJoseph Lo 
810de2114SJoseph Lo #include "tegra210-emc.h"
910de2114SJoseph Lo 
1010de2114SJoseph Lo #define TEGRA_EMC_MAX_FREQS		16
1110de2114SJoseph Lo 
1210de2114SJoseph Lo static int tegra210_emc_table_device_init(struct reserved_mem *rmem,
1310de2114SJoseph Lo 					  struct device *dev)
1410de2114SJoseph Lo {
1510de2114SJoseph Lo 	struct tegra210_emc *emc = dev_get_drvdata(dev);
1610de2114SJoseph Lo 	unsigned int i;
1710de2114SJoseph Lo 
1810de2114SJoseph Lo 	emc->timings = memremap(rmem->base, rmem->size, MEMREMAP_WB);
1910de2114SJoseph Lo 	if (!emc->timings) {
2010de2114SJoseph Lo 		dev_err(dev, "failed to map EMC table\n");
2110de2114SJoseph Lo 		return -ENOMEM;
2210de2114SJoseph Lo 	}
2310de2114SJoseph Lo 
2410de2114SJoseph Lo 	emc->num_timings = 0;
2510de2114SJoseph Lo 
2610de2114SJoseph Lo 	for (i = 0; i < TEGRA_EMC_MAX_FREQS; i++) {
2710de2114SJoseph Lo 		if (emc->timings[i].revision == 0)
2810de2114SJoseph Lo 			break;
2910de2114SJoseph Lo 
3010de2114SJoseph Lo 		emc->num_timings++;
3110de2114SJoseph Lo 	}
3210de2114SJoseph Lo 
3310de2114SJoseph Lo 	return 0;
3410de2114SJoseph Lo }
3510de2114SJoseph Lo 
3610de2114SJoseph Lo static void tegra210_emc_table_device_release(struct reserved_mem *rmem,
3710de2114SJoseph Lo 					      struct device *dev)
3810de2114SJoseph Lo {
3910de2114SJoseph Lo 	struct tegra210_emc *emc = dev_get_drvdata(dev);
4010de2114SJoseph Lo 
4110de2114SJoseph Lo 	memunmap(emc->timings);
4210de2114SJoseph Lo }
4310de2114SJoseph Lo 
4410de2114SJoseph Lo static const struct reserved_mem_ops tegra210_emc_table_ops = {
4510de2114SJoseph Lo 	.device_init = tegra210_emc_table_device_init,
4610de2114SJoseph Lo 	.device_release = tegra210_emc_table_device_release,
4710de2114SJoseph Lo };
4810de2114SJoseph Lo 
4910de2114SJoseph Lo static int tegra210_emc_table_init(struct reserved_mem *rmem)
5010de2114SJoseph Lo {
5110de2114SJoseph Lo 	pr_debug("Tegra210 EMC table at %pa, size %lu bytes\n", &rmem->base,
5210de2114SJoseph Lo 		 (unsigned long)rmem->size);
5310de2114SJoseph Lo 
5410de2114SJoseph Lo 	rmem->ops = &tegra210_emc_table_ops;
5510de2114SJoseph Lo 
5610de2114SJoseph Lo 	return 0;
5710de2114SJoseph Lo }
5810de2114SJoseph Lo RESERVEDMEM_OF_DECLARE(tegra210_emc_table, "nvidia,tegra210-emc-table",
5910de2114SJoseph Lo 		       tegra210_emc_table_init);
60