18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * mach-davinci/sram.c - DaVinci simple SRAM allocator
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2009 David Brownell
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#include <linux/module.h>
88c2ecf20Sopenharmony_ci#include <linux/init.h>
98c2ecf20Sopenharmony_ci#include <linux/io.h>
108c2ecf20Sopenharmony_ci#include <linux/genalloc.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <mach/common.h>
138c2ecf20Sopenharmony_ci#include "sram.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic struct gen_pool *sram_pool;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistruct gen_pool *sram_get_gen_pool(void)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	return sram_pool;
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_civoid *sram_alloc(size_t len, dma_addr_t *dma)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	dma_addr_t dma_base = davinci_soc_info.sram_dma;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	if (dma)
278c2ecf20Sopenharmony_ci		*dma = 0;
288c2ecf20Sopenharmony_ci	if (!sram_pool || (dma && !dma_base))
298c2ecf20Sopenharmony_ci		return NULL;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	return gen_pool_dma_alloc(sram_pool, len, dma);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sram_alloc);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_civoid sram_free(void *addr, size_t len)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	gen_pool_free(sram_pool, (unsigned long) addr, len);
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sram_free);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/*
448c2ecf20Sopenharmony_ci * REVISIT This supports CPU and DMA access to/from SRAM, but it
458c2ecf20Sopenharmony_ci * doesn't (yet?) support some other notable uses of SRAM:  as TCM
468c2ecf20Sopenharmony_ci * for data and/or instructions; and holding code needed to enter
478c2ecf20Sopenharmony_ci * and exit suspend states (while DRAM can't be used).
488c2ecf20Sopenharmony_ci */
498c2ecf20Sopenharmony_cistatic int __init sram_init(void)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	phys_addr_t phys = davinci_soc_info.sram_dma;
528c2ecf20Sopenharmony_ci	unsigned len = davinci_soc_info.sram_len;
538c2ecf20Sopenharmony_ci	int status = 0;
548c2ecf20Sopenharmony_ci	void __iomem *addr;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	if (len) {
578c2ecf20Sopenharmony_ci		len = min_t(unsigned, len, SRAM_SIZE);
588c2ecf20Sopenharmony_ci		sram_pool = gen_pool_create(ilog2(SRAM_GRANULARITY), -1);
598c2ecf20Sopenharmony_ci		if (!sram_pool)
608c2ecf20Sopenharmony_ci			status = -ENOMEM;
618c2ecf20Sopenharmony_ci	}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	if (sram_pool) {
648c2ecf20Sopenharmony_ci		addr = ioremap(phys, len);
658c2ecf20Sopenharmony_ci		if (!addr)
668c2ecf20Sopenharmony_ci			return -ENOMEM;
678c2ecf20Sopenharmony_ci		status = gen_pool_add_virt(sram_pool, (unsigned long) addr,
688c2ecf20Sopenharmony_ci					   phys, len, -1);
698c2ecf20Sopenharmony_ci		if (status < 0)
708c2ecf20Sopenharmony_ci			iounmap(addr);
718c2ecf20Sopenharmony_ci	}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	WARN_ON(status < 0);
748c2ecf20Sopenharmony_ci	return status;
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_cicore_initcall(sram_init);
778c2ecf20Sopenharmony_ci
78