summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2023-01-11 18:40:17 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2023-01-16 11:22:48 +0100
commitd8553561986e1258ba22748ba56b3322fa0b4eb3 (patch)
tree104b87b90fafdbd6eaadfc40cc740679a2567927 /lib
parent536d17c20a6fd488652ebb28975245dd8b292501 (diff)
downloadbarebox-d8553561986e1258ba22748ba56b3322fa0b4eb3.tar.gz
barebox-d8553561986e1258ba22748ba56b3322fa0b4eb3.tar.xz
lib: provide stub Linux "generic" allocator API
We may want to port the whole of the Linux generic allocator implementation in future as it would come in handy in drivers that need special memory for DMA. For now, support just the use case of the incoming Atmel NAND driver, which is mapping the whole of a mmio-sram. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20230111174023.1719129-10-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig5
-rw-r--r--lib/Makefile1
-rw-r--r--lib/genalloc.c118
3 files changed, 124 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index a0f28b935c..40a5fadd5c 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -205,4 +205,9 @@ config ARCH_HAS_ZERO_PAGE
config HAVE_EFFICIENT_UNALIGNED_ACCESS
bool
+config GENERIC_ALLOCATOR
+ bool
+ help
+ Support is curently limited to allocaing a complete mmio-sram at once.
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 21afb233fa..ba3cf6443f 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_CRC8) += crc8.o
obj-$(CONFIG_NLS) += nls_base.o
obj-$(CONFIG_FSL_QE_FIRMWARE) += fsl-qe-firmware.o
obj-$(CONFIG_UBSAN) += ubsan.o
+obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
# GCC library routines
obj-$(CONFIG_GENERIC_LIB_ASHLDI3) += ashldi3.o
diff --git a/lib/genalloc.c b/lib/genalloc.c
new file mode 100644
index 0000000000..906e2dd5f1
--- /dev/null
+++ b/lib/genalloc.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2005 Jes Sorensen <jes@trained-monkey.org>
+/*
+ * Basic general purpose allocator for managing special purpose
+ * memory, for example, memory that is not managed by the regular
+ * kmalloc/kfree interface. Uses for this includes on-device special
+ * memory, uncached memory etc.
+ */
+
+#include <io.h>
+#include <linux/ioport.h>
+#include <linux/genalloc.h>
+#include <linux/export.h>
+#include <of.h>
+#include <driver.h>
+#include <linux/string.h>
+
+struct gen_pool {
+ struct resource res;
+};
+
+#define res_to_gen_pool(res) \
+ container_of(res, struct gen_pool, res)
+
+/**
+ * gen_pool_virt_to_phys - return the physical address of memory
+ * @pool: pool to allocate from
+ * @addr: starting address of memory
+ *
+ * Returns the physical address on success, or -1 on error.
+ */
+phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr)
+{
+ return virt_to_phys((void *)addr);
+}
+EXPORT_SYMBOL(gen_pool_virt_to_phys);
+
+/**
+ * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage
+ * @pool: pool to allocate from
+ * @size: number of bytes to allocate from the pool
+ * @dma: dma-view physical address return value. Use %NULL if unneeded.
+ *
+ * Allocate the requested number of bytes from the specified pool.
+ * Uses the pool allocation function (with first-fit algorithm by default).
+ * Can not be used in NMI handler on architectures without
+ * NMI-safe cmpxchg implementation.
+ *
+ * Return: virtual address of the allocated memory, or %NULL on failure
+ */
+void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
+{
+ unsigned long vaddr;
+
+ if (!pool || resource_size(&pool->res) != size)
+ return NULL;
+
+ vaddr = pool->res.start;
+
+ if (dma)
+ *dma = gen_pool_virt_to_phys(pool, vaddr);
+
+ return (void *)vaddr;
+}
+EXPORT_SYMBOL(gen_pool_dma_alloc);
+
+/**
+ * gen_pool_dma_zalloc - allocate special zeroed memory from the pool for
+ * DMA usage
+ * @pool: pool to allocate from
+ * @size: number of bytes to allocate from the pool
+ * @dma: dma-view physical address return value. Use %NULL if unneeded.
+ *
+ * Return: virtual address of the allocated zeroed memory, or %NULL on failure
+ */
+void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
+{
+ void *vaddr = gen_pool_dma_alloc(pool, size, dma);
+
+ if (vaddr)
+ memset(vaddr, 0, size);
+
+ return vaddr;
+}
+EXPORT_SYMBOL(gen_pool_dma_zalloc);
+
+#ifdef CONFIG_OFDEVICE
+/**
+ * of_gen_pool_get - find a pool by phandle property
+ * @np: device node
+ * @propname: property name containing phandle(s)
+ * @index: index into the phandle array
+ *
+ * Returns the pool that contains the chunk starting at the physical
+ * address of the device tree node pointed at by the phandle property,
+ * or NULL if not found.
+ */
+struct gen_pool *of_gen_pool_get(struct device_node *np,
+ const char *propname, int index)
+{
+ struct device *dev;
+ struct device_node *np_pool;
+
+ np_pool = of_parse_phandle(np, propname, index);
+ if (!np_pool)
+ return NULL;
+
+ if (!of_device_is_compatible(np_pool, "mmio-sram"))
+ return NULL;
+
+ dev = of_find_device_by_node(np_pool);
+ if (!dev)
+ return NULL;
+
+ return container_of(&dev->resource[0], struct gen_pool, res);
+}
+EXPORT_SYMBOL_GPL(of_gen_pool_get);
+#endif /* CONFIG_OF */