1 /* 2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved. 3 * 4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in 5 * the the People's Republic of China and other countries. 6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission. 7 * 8 * DISCLAIMER 9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT. 10 * IF YOU NEED TO INTEGRATE THIRD PARTY¡¯S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.) 11 * IN ALLWINNERS¡¯SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN 12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES. 13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS 14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE. 15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY¡¯S TECHNOLOGY. 16 * 17 * 18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT 19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND, 20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING 21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE 22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30 * OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 #ifndef __SUNXI_HAL_DMA_H__ 33 #define __SUNXI_HAL_DMA_H__ 34 35 #include <stdint.h> 36 #include <stdbool.h> 37 #include <stdio.h> 38 39 /* 40 * include the platform dma header file. 41 */ 42 #include <dma/platform-dma.h> 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 /* #define DMA_DEBUG */ 49 50 #define HEXADECIMAL (0x10) 51 #define REG_INTERVAL (0x04) 52 #define REG_CL (0x0c) 53 54 //TODO:move reg list to sunxiwxx.h 55 #define HIGH_CHAN 8 56 57 #define DMA_IRQ_EN(x) (SUNXI_DMAC_PBASE + (0x00 + ((x) << 2))) /* Interrupt enable register */ 58 #define DMA_IRQ_STAT(x) (SUNXI_DMAC_PBASE + (0x10 + ((x) << 2))) /* Interrupt status register */ 59 #define DMA_SECURE (SUNXI_DMAC_PBASE + 0x20) /* DMA security register */ 60 #define DMA_GATE (SUNXI_DMAC_PBASE + 0x28) /* DMA gating register */ 61 #define DMA_MCLK_GATE 0x04 62 #define DMA_COMMON_GATE 0x02 63 #define DMA_CHAN_GATE 0x01 64 #define DMA_STAT (SUNXI_DMAC_PBASE + 0x30) /* DMA Status Register RO */ 65 #define DMA_ENABLE(x) (SUNXI_DMAC_PBASE + (0x100 + ((x + START_CHAN_OFFSET) << 6))) /* Channels enable register */ 66 #define DMA_PAUSE(x) (SUNXI_DMAC_PBASE + (0x104 + ((x + START_CHAN_OFFSET) << 6))) /* DMA Channels pause register */ 67 #define DMA_LLI_ADDR(x) (SUNXI_DMAC_PBASE + (0x108 + ((x + START_CHAN_OFFSET) << 6))) /* Descriptor address register */ 68 #define DMA_CFG(x) (SUNXI_DMAC_PBASE + (0x10C + ((x + START_CHAN_OFFSET) << 6))) /* Configuration register RO */ 69 #define DMA_CUR_SRC(x) (SUNXI_DMAC_PBASE + (0x110 + ((x + START_CHAN_OFFSET) << 6))) /* Current source address RO */ 70 #define DMA_CUR_DST(x) (SUNXI_DMAC_PBASE + (0x114 + ((x + START_CHAN_OFFSET) << 6))) /* Current destination address RO */ 71 #define DMA_CNT(x) (SUNXI_DMAC_PBASE + (0x118 + ((x + START_CHAN_OFFSET) << 6))) /* Byte counter left register RO */ 72 #define DMA_PARA(x) (SUNXI_DMAC_PBASE + (0x11C + ((x + START_CHAN_OFFSET) << 6))) /* Parameter register RO */ 73 #define LINK_END 0xFFFFF800 /* lastest link must be 0xfffff800 */ 74 75 /* DMA mode register */ 76 #define DMA_OP_MODE(x) (SUNXI_DMAC_PBASE + (0x128 + ((x + START_CHAN_OFFSET) << 6))) /* DMA mode register */ 77 #define SRC_HS_MASK (0x1 << 2) /* bit 2: Source handshake mode */ 78 #define DST_HS_MASK (0x1 << 3) /* bit 3: Destination handshake mode */ 79 80 #define SET_OP_MODE(x, val) ({ \ 81 writel(val,DMA_OP_MODE(x)); \ 82 }) 83 84 85 #define SHIFT_IRQ_MASK(val, ch) ({ \ 86 (ch + START_CHAN_OFFSET) >= HIGH_CHAN \ 87 ? (val) << ((ch + START_CHAN_OFFSET - HIGH_CHAN) << 2) \ 88 : (val) << ((ch + START_CHAN_OFFSET) << 2); \ 89 }) 90 91 #define SHIFT_PENDING_MASK(val, ch) ({ \ 92 (ch + START_CHAN_OFFSET) >= HIGH_CHAN \ 93 ? (val) << ((ch + START_CHAN_OFFSET - HIGH_CHAN) << 2) \ 94 : (val) << ((ch + START_CHAN_OFFSET) << 2); \ 95 }) 96 97 #define IRQ_HALF 0x01 /* Half package transfer interrupt pending */ 98 #define IRQ_PKG 0x02 /* One package complete interrupt pending */ 99 #define IRQ_QUEUE 0x04 /* All list complete transfer interrupt pending */ 100 101 /* DMA channel configuration register */ 102 /* The detail information of DMA configuration */ 103 #define SRC_WIDTH(x) ((x) << 9) 104 #define SRC_BURST(x) ((x) << 6) 105 #define SRC_IO_MODE (0x01 << 8) 106 #define SRC_LINEAR_MODE (0x00 << 8) 107 #define SRC_DRQ(x) ((x) << 0) 108 #define DST_WIDTH(x) ((x) << 25) 109 #define DST_BURST(x) ((x) << 22) 110 #define DST_IO_MODE (0x01 << 24) 111 #define DST_LINEAR_MODE (0x00 << 24) 112 #define DST_DRQ(x) ((x) << 16) 113 #define CHAN_START 1 114 #define CHAN_STOP 0 115 #define CHAN_PAUSE 1 116 #define CHAN_RESUME 0 117 #define NORMAL_WAIT (8 << 0) 118 119 #define GET_SRC_DRQ(x) ((x) & 0x000000ff) 120 #define GET_DST_DRQ(x) ((x) & 0x00ff0000) 121 122 struct sunxi_dma_lli { 123 uint32_t cfg; 124 uint32_t src; 125 uint32_t dst; 126 uint32_t len; 127 uint32_t para; 128 uint32_t p_lln; 129 struct sunxi_dma_lli *vlln; 130 }; 131 132 133 #define sunxi_slave_id(d, s) (((d)<<16) | (s)) 134 135 typedef void (*dma_callback)(void *param); 136 137 /** 138 * enum dma_slave_buswidth - defines bus width of the DMA slave 139 * device, source or target buses 140 */ 141 enum dma_slave_buswidth { 142 DMA_SLAVE_BUSWIDTH_UNDEFINED = 0, 143 DMA_SLAVE_BUSWIDTH_1_BYTE = 1, 144 DMA_SLAVE_BUSWIDTH_2_BYTES = 2, 145 DMA_SLAVE_BUSWIDTH_3_BYTES = 3, 146 DMA_SLAVE_BUSWIDTH_4_BYTES = 4, 147 DMA_SLAVE_BUSWIDTH_8_BYTES = 8, 148 DMA_SLAVE_BUSWIDTH_16_BYTES = 16, 149 DMA_SLAVE_BUSWIDTH_32_BYTES = 32, 150 DMA_SLAVE_BUSWIDTH_64_BYTES = 64, 151 }; 152 153 enum dma_slave_burst { 154 DMA_SLAVE_BURST_1 = 1, 155 DMA_SLAVE_BURST_4 = 4, 156 DMA_SLAVE_BURST_8 = 8, 157 DMA_SLAVE_BURST_16 = 16, 158 }; 159 160 /** 161 * enum dma_transfer_direction - dma transfer mode and direction indicator 162 * @DMA_MEM_TO_MEM: Async/Memcpy mode 163 * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device 164 * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory 165 * @DMA_DEV_TO_DEV: Slave mode & From Device to Device 166 */ 167 enum dma_transfer_direction { 168 DMA_MEM_TO_MEM = 0, 169 DMA_MEM_TO_DEV = 1, 170 DMA_DEV_TO_MEM = 2, 171 DMA_DEV_TO_DEV = 3, 172 DMA_TRANS_NONE, 173 }; 174 175 /** 176 * enum dma_status - DMA transaction status 177 * @DMA_COMPLETE: transaction completed 178 * @DMA_IN_PROGRESS: transaction not yet processed 179 * @DMA_PAUSED: transaction is paused 180 * @DMA_ERROR: transaction failed 181 */ 182 enum dma_status { 183 DMA_INVALID_PARAMETER = -2, 184 DMA_ERROR = -1, 185 DMA_COMPLETE, 186 DMA_IN_PROGRESS, 187 DMA_PAUSED, 188 }; 189 190 /** 191 * struct dma_slave_config - dma slave channel runtime config 192 * @direction: whether the data shall go in or out on this slave 193 * channel, right now. DMA_MEM_TO_DEV and DMA_DEV_TO_MEM are 194 * legal values. DEPRECATED, drivers should use the direction argument 195 * to the device_prep_slave_sg and device_prep_dma_cyclic functions or 196 * the dir field in the dma_interleaved_template structure. 197 * @src_addr: this is the physical address where DMA slave data 198 * should be read (RX), if the source is memory this argument is 199 * ignored. 200 * @dst_addr: this is the physical address where DMA slave data 201 * should be written (TX), if the source is memory this argument 202 * is ignored. 203 * @src_addr_width: this is the width in bytes of the source (RX) 204 * register where DMA data shall be read. If the source 205 * is memory this may be ignored depending on architecture. 206 * Legal values: 1, 2, 4, 8. 207 * @dst_addr_width: same as src_addr_width but for destination 208 * target (TX) mutatis mutandis. 209 * @src_maxburst: the maximum number of words (note: words, as in 210 * units of the src_addr_width member, not bytes) that can be sent 211 * in one burst to the device. Typically something like half the 212 * FIFO depth on I/O peripherals so you don't overflow it. This 213 * may or may not be applicable on memory sources. 214 * @dst_maxburst: same as src_maxburst but for destination target 215 * mutatis mutandis. 216 * @slave_id: Slave requester id. Only valid for slave channels. The dma 217 * slave peripheral will have unique id as dma requester which need to be 218 * pass as slave config. 219 * 220 * This struct is passed in as configuration data to a DMA engine 221 * in order to set up a certain channel for DMA transport at runtime. 222 * The DMA device/engine has to provide support for an additional 223 * callback in the dma_device structure, device_config and this struct 224 * will then be passed in as an argument to the function. 225 * 226 * The rationale for adding configuration information to this struct is as 227 * follows: if it is likely that more than one DMA slave controllers in 228 * the world will support the configuration option, then make it generic. 229 * If not: if it is fixed so that it be sent in static from the platform 230 * data, then prefer to do that. 231 */ 232 struct dma_slave_config { 233 enum dma_transfer_direction direction; 234 unsigned long src_addr; 235 unsigned long dst_addr; 236 enum dma_slave_buswidth src_addr_width; 237 enum dma_slave_buswidth dst_addr_width; 238 uint32_t src_maxburst; 239 uint32_t dst_maxburst; 240 uint32_t slave_id; 241 }; 242 243 struct sunxi_dma_chan { 244 uint8_t used:1; 245 uint8_t chan_count:4; 246 bool cyclic:1; 247 struct dma_slave_config cfg; 248 uint32_t periods_pos; 249 uint32_t buf_len; 250 struct sunxi_dma_lli *desc; 251 uint32_t irq_type; 252 dma_callback callback; 253 void *callback_param; 254 /* volatile kspinlock_t lock; */ 255 volatile int lock; 256 }; 257 258 /** This enum defines the DMA CHANNEL status. */ 259 typedef enum { 260 HAL_DMA_CHAN_STATUS_BUSY = 0, /* DMA channel status busy */ 261 HAL_DMA_CHAN_STATUS_FREE = 1 /* DMA channel status free */ 262 } hal_dma_chan_status_t; 263 264 /** This enum defines the return type of GPIO API. */ 265 typedef enum { 266 HAL_DMA_STATUS_INVALID_PARAMETER = -22, /* Invalid input parameter. */ 267 HAL_DMA_STATUS_NO_MEM = -12, /* No memory. */ 268 HAL_DMA_STATUS_ERR_PERM = -1, /* Operation not permitted. */ 269 HAL_DMA_STATUS_OK = 0 /* The DMA status ok. */ 270 } hal_dma_status_t; 271 272 273 hal_dma_chan_status_t hal_dma_chan_request(struct sunxi_dma_chan **dma_chan); 274 hal_dma_status_t hal_dma_prep_memcpy(struct sunxi_dma_chan *chan, 275 uint32_t dest, uint32_t src, uint32_t len); 276 hal_dma_status_t hal_dma_prep_device(struct sunxi_dma_chan *chan, 277 uint32_t dest, uint32_t src, 278 uint32_t len, enum dma_transfer_direction dir); 279 hal_dma_status_t hal_dma_prep_cyclic(struct sunxi_dma_chan *chan, 280 uint32_t buf_addr, uint32_t buf_len, 281 uint32_t period_len, enum dma_transfer_direction dir); 282 hal_dma_status_t hal_dma_callback_install(struct sunxi_dma_chan *chan, 283 dma_callback callback, 284 void *callback_param); 285 hal_dma_status_t hal_dma_slave_config(struct sunxi_dma_chan *chan, struct dma_slave_config *config); 286 enum dma_status hal_dma_tx_status(struct sunxi_dma_chan *chan, uint32_t *left_size); 287 hal_dma_status_t hal_dma_start(struct sunxi_dma_chan *chan); 288 hal_dma_status_t hal_dma_stop(struct sunxi_dma_chan *chan); 289 hal_dma_status_t hal_dma_chan_free(struct sunxi_dma_chan *chan); 290 hal_dma_status_t hal_dma_chan_desc_free(struct sunxi_dma_chan *chan); 291 void hal_dma_init(void); 292 293 #ifdef __cplusplus 294 } 295 #endif 296 297 #endif 298