Commit c6f39c7c authored by Herve Codina's avatar Herve Codina Committed by Christophe Leroy
Browse files

soc: fsl: qe: Add resource-managed muram allocators



Introduce devm_cpm_muram_alloc() and devm_cpm_muram_alloc_fixed(), the
resource-managed version of cpm_muram_alloc and cpm_muram_alloc_fixed().

These resource-managed versions simplify the user avoiding the need to
call cpm_muram_free(). Indeed, the allocated area returned by these
functions will be automatically freed on driver detach.

Signed-off-by: default avatarHerve Codina <herve.codina@bootlin.com>
Reviewed-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Link: https://lore.kernel.org/r/20240808071132.149251-33-herve.codina@bootlin.com


Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
parent b741b66f
Loading
Loading
Loading
Loading
+80 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
 * 2006 (c) MontaVista Software, Inc.
 * Vitaly Bordug <vbordug@ru.mvista.com>
 */
#include <linux/device.h>
#include <linux/genalloc.h>
#include <linux/init.h>
#include <linux/list.h>
@@ -187,6 +188,49 @@ void cpm_muram_free(s32 offset)
}
EXPORT_SYMBOL(cpm_muram_free);

static void devm_cpm_muram_release(struct device *dev, void *res)
{
	s32 *info = res;

	cpm_muram_free(*info);
}

/**
 * devm_cpm_muram_alloc - Resource-managed cpm_muram_alloc
 * @dev: Device to allocate memory for
 * @size: number of bytes to allocate
 * @align: requested alignment, in bytes
 *
 * This function returns a non-negative offset into the muram area, or
 * a negative errno on failure as cpm_muram_alloc() does.
 * Use cpm_muram_addr() to get the virtual address of the area.
 *
 * Compare against cpm_muram_alloc(), the memory allocated by this
 * resource-managed version is automatically freed on driver detach and so,
 * cpm_muram_free() must not be called to release the allocated memory.
 */
s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
			 unsigned long align)
{
	s32 info;
	s32 *dr;

	dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return -ENOMEM;

	info = cpm_muram_alloc(size, align);
	if (info >= 0) {
		*dr = info;
		devres_add(dev, dr);
	} else {
		devres_free(dr);
	}

	return info;
}
EXPORT_SYMBOL(devm_cpm_muram_alloc);

/*
 * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
 * @offset: offset of allocation start address
@@ -211,6 +255,42 @@ s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
}
EXPORT_SYMBOL(cpm_muram_alloc_fixed);

/**
 * devm_cpm_muram_alloc_fixed - Resource-managed cpm_muram_alloc_fixed
 * @dev: Device to allocate memory for
 * @offset: offset of allocation start address
 * @size: number of bytes to allocate
 *
 * This function returns a non-negative offset into the muram area, or
 * a negative errno on failure as cpm_muram_alloc_fixed() does.
 * Use cpm_muram_addr() to get the virtual address of the area.
 *
 * Compare against cpm_muram_alloc_fixed(), the memory allocated by this
 * resource-managed version is automatically freed on driver detach and so,
 * cpm_muram_free() must not be called to release the allocated memory.
 */
s32 devm_cpm_muram_alloc_fixed(struct device *dev, unsigned long offset,
			       unsigned long size)
{
	s32 info;
	s32 *dr;

	dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return -ENOMEM;

	info = cpm_muram_alloc_fixed(offset, size);
	if (info >= 0) {
		*dr = info;
		devres_add(dev, dr);
	} else {
		devres_free(dr);
	}

	return info;
}
EXPORT_SYMBOL(devm_cpm_muram_alloc_fixed);

/**
 * cpm_muram_addr - turn a muram offset into a virtual address
 * @offset: muram offset to convert
+21 −1
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include <linux/of_address.h>
#include <linux/types.h>

struct device;

#define QE_NUM_OF_SNUM	256	/* There are 256 serial number in QE */
#define QE_NUM_OF_BRGS	16
#define QE_NUM_OF_PORTS	1024
@@ -93,8 +95,12 @@ int cpm_muram_init(void);

#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
s32 cpm_muram_alloc(unsigned long size, unsigned long align);
s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
			 unsigned long align);
void cpm_muram_free(s32 offset);
s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
s32 devm_cpm_muram_alloc_fixed(struct device *dev, unsigned long offset,
			       unsigned long size);
void __iomem *cpm_muram_addr(unsigned long offset);
unsigned long cpm_muram_offset(const void __iomem *addr);
dma_addr_t cpm_muram_dma(void __iomem *addr);
@@ -106,6 +112,12 @@ static inline s32 cpm_muram_alloc(unsigned long size,
	return -ENOSYS;
}

static inline s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
				       unsigned long align)
{
	return -ENOSYS;
}

static inline void cpm_muram_free(s32 offset)
{
}
@@ -116,6 +128,13 @@ static inline s32 cpm_muram_alloc_fixed(unsigned long offset,
	return -ENOSYS;
}

static inline s32 devm_cpm_muram_alloc_fixed(struct device *dev,
					     unsigned long offset,
					     unsigned long size)
{
	return -ENOSYS;
}

static inline void __iomem *cpm_muram_addr(unsigned long offset)
{
	return NULL;
@@ -172,7 +191,6 @@ static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; }
/*
 * Pin multiplexing functions.
 */
struct device;
struct qe_pin;
#ifdef CONFIG_QE_GPIO
extern struct qe_pin *qe_pin_request(struct device *dev, int index);
@@ -233,7 +251,9 @@ static inline int qe_alive_during_sleep(void)
/* we actually use cpm_muram implementation, define this for convenience */
#define qe_muram_init cpm_muram_init
#define qe_muram_alloc cpm_muram_alloc
#define devm_qe_muram_alloc devm_cpm_muram_alloc
#define qe_muram_alloc_fixed cpm_muram_alloc_fixed
#define devm_qe_muram_alloc_fixed devm_cpm_muram_alloc_fixed
#define qe_muram_free cpm_muram_free
#define qe_muram_addr cpm_muram_addr
#define qe_muram_offset cpm_muram_offset