1/* 2 * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6/* Author: alex.kroh@nicta.com.au */ 7 8#pragma once 9 10#include <stdint.h> 11#include <stddef.h> 12#include <dma/dma.h> 13#include <platsupport/io.h> 14 15struct dma_allocator; 16typedef struct dma_mem *dma_mem_t; 17 18typedef void *vaddr_t; 19typedef uintptr_t paddr_t; 20 21/** 22 * Describes a chunk of memory for DMA use. 23 */ 24struct dma_mem_descriptor { 25 /** The virtual address of the memory. 26 It is the applications responsibility to perform the mapping operation. */ 27 uintptr_t vaddr; 28 /// The physical address of the memory. 29 uintptr_t paddr; 30 /** Boolian representation of the cacheability of the frames in this 31 descriptor. */ 32 int cached; 33 /// The size of each frame (2^frame_size_bits bytes) 34 int size_bits; 35 /// This field is unused and may be used by the bulk allocator 36 void *alloc_cookie; 37 /// This field is unused and may be used by the application. 38 void *cookie; 39}; 40 41 42/** 43 * DMA access flags. 44 * DMA access patterns are important to the DMA memory manager because cache 45 * maintenance operations may affect (corrupt) adjacent buffers. This is due 46 * to cach line size limits and software flushing granularity (perhaps the OS 47 * interface limits us to perform maintenance operations on a per page basis). 48 * 49 * These flags will generally lead to multiple memory pools where each request 50 * will be allocated from the appropriate pool. 51 */ 52enum dma_flags { 53 /// Host always reads, never writes (invalidate only) 54 DMAF_HR, 55 /// Host always writes, never reads (clean only) 56 DMAF_HW, 57 /// Host performs both read and write (clean/invalidate) 58 DMAF_HRW, 59 /// Explicitly request uncached DMA memory 60 DMAF_COHERENT 61}; 62 63 64/** 65 * A callback for providing DMA memory to the allocator. 66 * @param[in] min_size the minimum size for the allocation 67 * @param[in] cached 0 if the requested memory should not be cached. 68 * @param[out] dma_desc On return, this structure should be filled with a 69 * description of the memory that has been provided. 70 * @return 0 on success 71 */ 72typedef int (*dma_morecore_fn)(size_t min_size, int cached, 73 struct dma_mem_descriptor *dma_desc); 74 75/** 76 * Initialises a new DMA allocator for use with io_ops. 77 * @param[in] morecore A function to use when the allocator requires more DMA 78 * memory. NULL if the allocator should not request more 79 * memory. 80 * @param[in] cache_op Operations to use for cleaning/invalidating the cache 81 * @param[out] dma_man libplatsupport DMA manager structure to populate 82 * @return 0 on success 83 */ 84int dma_dmaman_init(dma_morecore_fn morecore, ps_dma_cache_op_fn_t cache_ops, 85 ps_dma_man_t *dma_man); 86 87 88/** 89 * Explicitly provides memory to the DMA allocator. 90 * @param[in] dma_desc A description of the memory provided. 91 * @return 0 on success 92 */ 93int dma_provide_mem(struct dma_allocator *allocator, 94 struct dma_mem_descriptor dma_desc); 95 96/** 97 * If possible, reclaim some memory from the DMA allocator. 98 * @param[in] allocator A handle to the allocator to reclaim memory from 99 * @param[out] dma_desc If the call is successful, this structure will 100 * be filled with a description of the memeory that 101 * has been released from the allocator. 102 * @return 0 on success, non-zero indicates that a suitable 103 * reclaim candidate could not be found. 104 */ 105int dma_reclaim_mem(struct dma_allocator *allocator, 106 struct dma_mem_descriptor *dma_desc); 107 108 109 110/****************** 111 * Legacy API 112 ******************/ 113 114/** 115 * Initialises a new DMA allocator. 116 * @param[in] morecore A function to use when the allocator requires more DMA 117 * memory. NULL if the allocator should not request more 118 * memory. 119 * @return A reference to a new DMA allocator instance. 120 */ 121struct dma_allocator *dma_allocator_init(dma_morecore_fn morecore); 122 123/** 124 * Retrieve the virtual address of allocated DMA memory. 125 * @param[in] dma_mem A handle to DMA memory. 126 * @return The virtual address of the DMA memory in question. 127 */ 128vaddr_t dma_vaddr(dma_mem_t dma_mem); 129 130/** 131 * Retrieve the physical address of allocated DMA memory. 132 * @param[in] dma_mem A handle to DMA memory. 133 * @return The physical address of the DMA memory in question. 134 */ 135paddr_t dma_paddr(dma_mem_t dma_mem); 136 137/** 138 * Flush DMA memory out to RAM by virtual address 139 * @param[in] dma_mem A handle to allocated DMA memory. 140 * @param[in] vstart The staring virtual address of the flush. 141 * @param[in] vend One greater than the last virtual address to be 142 * flushed. 143 */ 144void dma_clean(dma_mem_t dma_mem, vaddr_t vstart, vaddr_t vend); 145 146/** 147 * Invalidate DMA memory from cache by virtual address 148 * @param[in] dma_mem A handle to allocated DMA memory. 149 * @param[in] vstart The staring virtual address of the invalidation. 150 * @param[in] vend One greater than the last virtual address to be 151 * invalidated. 152 */ 153void dma_invalidate(dma_mem_t dma_mem, vaddr_t vstart, vaddr_t vend); 154 155/** 156 * Flush DMA memory out to RAM and invalidate the caches by virtual address. 157 * @param[in] dma_mem A handle to allocated DMA memory. 158 * @param[in] vstart The staring virtual address of the clean/invalidate. 159 * @param[in] vend One greater than the last virtual address to be 160 * cleaned/invalidated. 161 */ 162void dma_cleaninvalidate(dma_mem_t dma_mem, vaddr_t vstart, vaddr_t vend); 163 164/** 165 * Allocate DMA memory. 166 * @param[in] allocator The DMA allocator instance to use for the allocation. 167 * @param[in] size The allocation size. 168 * @param[in] align The minimum alignment (in bytes) of the allocated 169 * region. 170 * @param[in] flags The allocation properties of the request. 171 * @param[out] dma_mem If the call is successful and dma_mem is not NULL, 172 * dma_mem will contain a handle to the allocated memory. 173 * @return The virtual address of the allocated DMA memory, NULL 174 * on failure. 175 */ 176vaddr_t dma_alloc(struct dma_allocator *allocator, size_t size, int align, 177 enum dma_flags flags, dma_mem_t *dma_mem); 178 179/** 180 * Free DMA memory by virtual address. 181 * @param[in] dma_mem A handle to the DMA memory to free. 182 */ 183void dma_free(dma_mem_t dma_mem); 184 185 186/** 187 * Retrieve the DMA memory handle from a given physical address. 188 * The performance of this operation is likely to be poor, but it may be useful 189 * for rapid prototyping or debugging. 190 * @param[in] allocator The allocator managing the memory. 191 * @param[in] paddr The physical address of the memory in question 192 * @return The DMA memory handle associated with the 193 * provided physical address. NULL if the physical 194 * address is not managed by the provided allocator. 195 */ 196dma_mem_t dma_plookup(struct dma_allocator *allocator, paddr_t paddr); 197 198/** 199 * Retrieve the DMA memory handle from a given virtual address. 200 * The performance of this operation is likely to be poor, but it may be useful 201 * for rapid prototyping or debugging. 202 * @param[in] allocator The allocator managing the memory. 203 * @param[in] vaddr The virtual address of the memory in question 204 * @return The DMA memory handle associated with the 205 * provided virtual address. NULL if the physical 206 * address is not managed by the provided allocator. 207 */ 208dma_mem_t dma_vlookup(struct dma_allocator *allocator, vaddr_t vaddr); 209