/* max address size we deal with */ #define OF_MAX_ADDR_CELLS 4 #define GENPOOL_OFFSET (4096 * 8)
int cpm_muram_init(void)
{ struct device_node *np; struct resource r;
__be32 zero[OF_MAX_ADDR_CELLS] = {};
resource_size_t max = 0; int i = 0; int ret = 0;
if (muram_pbase) return 0;
np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data"); if (!np) { /* try legacy bindings */
np = of_find_node_by_name(NULL, "data-only"); if (!np) {
pr_err("Cannot find CPM muram data node");
ret = -ENODEV; goto out_muram;
}
}
muram_pool = gen_pool_create(0, -1); if (!muram_pool) {
pr_err("Cannot allocate memory pool for CPM/QE muram");
ret = -ENOMEM; goto out_muram;
}
muram_pbase = of_translate_address(np, zero); if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) {
pr_err("Cannot translate zero through CPM muram node");
ret = -ENODEV; goto out_pool;
}
while (of_address_to_resource(np, i++, &r) == 0) { if (r.end > max)
max = r.end;
ret = gen_pool_add(muram_pool, r.start - muram_pbase +
GENPOOL_OFFSET, resource_size(&r), -1); if (ret) {
pr_err("QE: couldn't add muram to pool!\n"); goto out_pool;
}
}
muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1); if (!muram_vbase) {
pr_err("Cannot map QE muram");
ret = -ENOMEM; goto out_pool;
} goto out_muram;
out_pool:
gen_pool_destroy(muram_pool);
out_muram:
of_node_put(np); return ret;
}
/* * cpm_muram_alloc_common - cpm_muram_alloc common code * @size: number of bytes to allocate * @algo: algorithm for alloc. * @data: data for genalloc's algorithm. * * This function returns a non-negative offset into the muram area, or * a negative errno on failure.
*/ static s32 cpm_muram_alloc_common(unsignedlong size,
genpool_algo_t algo, void *data)
{ struct muram_block *entry;
s32 start;
/* * cpm_muram_alloc - allocate the requested size worth of multi-user ram * @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. * Use cpm_muram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation.
*/
s32 cpm_muram_alloc(unsignedlong size, unsignedlong align)
{
s32 start; unsignedlong flags; struct genpool_data_align muram_pool_data;
/** * cpm_muram_free - free a chunk of multi-user ram * @offset: The beginning of the chunk as returned by cpm_muram_alloc().
*/ void cpm_muram_free(s32 offset)
{ unsignedlong flags; int size; struct muram_block *tmp;
/** * 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, unsignedlong size, unsignedlong 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);
}
/* * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram * @offset: offset of allocation start address * @size: number of bytes to allocate * This function returns @offset if the area was available, a negative * errno otherwise. * Use cpm_muram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation.
*/
s32 cpm_muram_alloc_fixed(unsignedlong offset, unsignedlong size)
{
s32 start; unsignedlong flags; struct genpool_data_fixed muram_pool_data_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, unsignedlong offset, unsignedlong 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);
}
/** * cpm_muram_dma - turn a muram virtual address into a DMA address * @addr: virtual address from cpm_muram_addr() to convert
*/
dma_addr_t cpm_muram_dma(void __iomem *addr)
{ return muram_pbase + (addr - muram_vbase);
}
EXPORT_SYMBOL(cpm_muram_dma);
/* * As cpm_muram_free, but takes the virtual address rather than the * muram offset.
*/ void cpm_muram_free_addr(constvoid __iomem *addr)
{ if (!addr) return;
cpm_muram_free(cpm_muram_offset(addr));
}
EXPORT_SYMBOL(cpm_muram_free_addr);
Messung V0.5
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.