blob: e42d1c9847ff095471485105187e3dd73970ef8e [file] [log] [blame] [edit]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/
/* Author: alex.kroh@nicta.com.au */
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <dma/dma.h>
#include <platsupport/io.h>
struct dma_allocator;
typedef struct dma_mem *dma_mem_t;
typedef void *vaddr_t;
typedef uintptr_t paddr_t;
/**
* Describes a chunk of memory for DMA use.
*/
struct dma_mem_descriptor {
/** The virtual address of the memory.
It is the applications responsibility to perform the mapping operation. */
uintptr_t vaddr;
/// The physical address of the memory.
uintptr_t paddr;
/** Boolian representation of the cacheability of the frames in this
descriptor. */
int cached;
/// The size of each frame (2^frame_size_bits bytes)
int size_bits;
/// This field is unused and may be used by the bulk allocator
void *alloc_cookie;
/// This field is unused and may be used by the application.
void *cookie;
};
/**
* DMA access flags.
* DMA access patterns are important to the DMA memory manager because cache
* maintenance operations may affect (corrupt) adjacent buffers. This is due
* to cach line size limits and software flushing granularity (perhaps the OS
* interface limits us to perform maintenance operations on a per page basis).
*
* These flags will generally lead to multiple memory pools where each request
* will be allocated from the appropriate pool.
*/
enum dma_flags {
/// Host always reads, never writes (invalidate only)
DMAF_HR,
/// Host always writes, never reads (clean only)
DMAF_HW,
/// Host performs both read and write (clean/invalidate)
DMAF_HRW,
/// Explicitly request uncached DMA memory
DMAF_COHERENT
};
/**
* A callback for providing DMA memory to the allocator.
* @param[in] min_size the minimum size for the allocation
* @param[in] cached 0 if the requested memory should not be cached.
* @param[out] dma_desc On return, this structure should be filled with a
* description of the memory that has been provided.
* @return 0 on success
*/
typedef int (*dma_morecore_fn)(size_t min_size, int cached,
struct dma_mem_descriptor *dma_desc);
/**
* Initialises a new DMA allocator for use with io_ops.
* @param[in] morecore A function to use when the allocator requires more DMA
* memory. NULL if the allocator should not request more
* memory.
* @param[in] cache_op Operations to use for cleaning/invalidating the cache
* @param[out] dma_man libplatsupport DMA manager structure to populate
* @return 0 on success
*/
int dma_dmaman_init(dma_morecore_fn morecore, ps_dma_cache_op_fn_t cache_ops,
ps_dma_man_t *dma_man);
/**
* Explicitly provides memory to the DMA allocator.
* @param[in] dma_desc A description of the memory provided.
* @return 0 on success
*/
int dma_provide_mem(struct dma_allocator *allocator,
struct dma_mem_descriptor dma_desc);
/**
* If possible, reclaim some memory from the DMA allocator.
* @param[in] allocator A handle to the allocator to reclaim memory from
* @param[out] dma_desc If the call is successful, this structure will
* be filled with a description of the memeory that
* has been released from the allocator.
* @return 0 on success, non-zero indicates that a suitable
* reclaim candidate could not be found.
*/
int dma_reclaim_mem(struct dma_allocator *allocator,
struct dma_mem_descriptor *dma_desc);
/******************
* Legacy API
******************/
/**
* Initialises a new DMA allocator.
* @param[in] morecore A function to use when the allocator requires more DMA
* memory. NULL if the allocator should not request more
* memory.
* @return A reference to a new DMA allocator instance.
*/
struct dma_allocator *dma_allocator_init(dma_morecore_fn morecore);
/**
* Retrieve the virtual address of allocated DMA memory.
* @param[in] dma_mem A handle to DMA memory.
* @return The virtual address of the DMA memory in question.
*/
vaddr_t dma_vaddr(dma_mem_t dma_mem);
/**
* Retrieve the physical address of allocated DMA memory.
* @param[in] dma_mem A handle to DMA memory.
* @return The physical address of the DMA memory in question.
*/
paddr_t dma_paddr(dma_mem_t dma_mem);
/**
* Flush DMA memory out to RAM by virtual address
* @param[in] dma_mem A handle to allocated DMA memory.
* @param[in] vstart The staring virtual address of the flush.
* @param[in] vend One greater than the last virtual address to be
* flushed.
*/
void dma_clean(dma_mem_t dma_mem, vaddr_t vstart, vaddr_t vend);
/**
* Invalidate DMA memory from cache by virtual address
* @param[in] dma_mem A handle to allocated DMA memory.
* @param[in] vstart The staring virtual address of the invalidation.
* @param[in] vend One greater than the last virtual address to be
* invalidated.
*/
void dma_invalidate(dma_mem_t dma_mem, vaddr_t vstart, vaddr_t vend);
/**
* Flush DMA memory out to RAM and invalidate the caches by virtual address.
* @param[in] dma_mem A handle to allocated DMA memory.
* @param[in] vstart The staring virtual address of the clean/invalidate.
* @param[in] vend One greater than the last virtual address to be
* cleaned/invalidated.
*/
void dma_cleaninvalidate(dma_mem_t dma_mem, vaddr_t vstart, vaddr_t vend);
/**
* Allocate DMA memory.
* @param[in] allocator The DMA allocator instance to use for the allocation.
* @param[in] size The allocation size.
* @param[in] align The minimum alignment (in bytes) of the allocated
* region.
* @param[in] flags The allocation properties of the request.
* @param[out] dma_mem If the call is successful and dma_mem is not NULL,
* dma_mem will contain a handle to the allocated memory.
* @return The virtual address of the allocated DMA memory, NULL
* on failure.
*/
vaddr_t dma_alloc(struct dma_allocator *allocator, size_t size, int align,
enum dma_flags flags, dma_mem_t *dma_mem);
/**
* Free DMA memory by virtual address.
* @param[in] dma_mem A handle to the DMA memory to free.
*/
void dma_free(dma_mem_t dma_mem);
/**
* Retrieve the DMA memory handle from a given physical address.
* The performance of this operation is likely to be poor, but it may be useful
* for rapid prototyping or debugging.
* @param[in] allocator The allocator managing the memory.
* @param[in] paddr The physical address of the memory in question
* @return The DMA memory handle associated with the
* provided physical address. NULL if the physical
* address is not managed by the provided allocator.
*/
dma_mem_t dma_plookup(struct dma_allocator *allocator, paddr_t paddr);
/**
* Retrieve the DMA memory handle from a given virtual address.
* The performance of this operation is likely to be poor, but it may be useful
* for rapid prototyping or debugging.
* @param[in] allocator The allocator managing the memory.
* @param[in] vaddr The virtual address of the memory in question
* @return The DMA memory handle associated with the
* provided virtual address. NULL if the physical
* address is not managed by the provided allocator.
*/
dma_mem_t dma_vlookup(struct dma_allocator *allocator, vaddr_t vaddr);