1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates. 4 * Synopsys DesignWare eDMA core driver 5 * 6 * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com> 7 */ 8 9#ifndef _DW_EDMA_CORE_H 10#define _DW_EDMA_CORE_H 11 12#include <linux/msi.h> 13#include <linux/dma/edma.h> 14 15#include "../virt-dma.h" 16 17#define EDMA_LL_SZ 24 18 19enum dw_edma_dir { 20 EDMA_DIR_WRITE = 0, 21 EDMA_DIR_READ 22}; 23 24enum dw_edma_request { 25 EDMA_REQ_NONE = 0, 26 EDMA_REQ_STOP, 27 EDMA_REQ_PAUSE 28}; 29 30enum dw_edma_status { 31 EDMA_ST_IDLE = 0, 32 EDMA_ST_PAUSE, 33 EDMA_ST_BUSY 34}; 35 36enum dw_edma_xfer_type { 37 EDMA_XFER_SCATTER_GATHER = 0, 38 EDMA_XFER_CYCLIC, 39 EDMA_XFER_INTERLEAVED 40}; 41 42struct dw_edma_chan; 43struct dw_edma_chunk; 44 45struct dw_edma_burst { 46 struct list_head list; 47 u64 sar; 48 u64 dar; 49 u32 sz; 50}; 51 52struct dw_edma_chunk { 53 struct list_head list; 54 struct dw_edma_chan *chan; 55 struct dw_edma_burst *burst; 56 57 u32 bursts_alloc; 58 59 u8 cb; 60 struct dw_edma_region ll_region; /* Linked list */ 61}; 62 63struct dw_edma_desc { 64 struct virt_dma_desc vd; 65 struct dw_edma_chan *chan; 66 struct dw_edma_chunk *chunk; 67 68 u32 chunks_alloc; 69 70 u32 alloc_sz; 71 u32 xfer_sz; 72}; 73 74struct dw_edma_chan { 75 struct virt_dma_chan vc; 76 struct dw_edma *dw; 77 int id; 78 enum dw_edma_dir dir; 79 80 u32 ll_max; 81 82 struct msi_msg msi; 83 84 enum dw_edma_request request; 85 enum dw_edma_status status; 86 u8 configured; 87 88 struct dma_slave_config config; 89}; 90 91struct dw_edma_irq { 92 struct msi_msg msi; 93 u32 wr_mask; 94 u32 rd_mask; 95 struct dw_edma *dw; 96}; 97 98struct dw_edma { 99 char name[32]; 100 101 struct dma_device dma; 102 103 u16 wr_ch_cnt; 104 u16 rd_ch_cnt; 105 106 struct dw_edma_irq *irq; 107 int nr_irqs; 108 109 struct dw_edma_chan *chan; 110 111 raw_spinlock_t lock; /* Only for legacy */ 112 113 struct dw_edma_chip *chip; 114 115 const struct dw_edma_core_ops *core; 116}; 117 118typedef void (*dw_edma_handler_t)(struct dw_edma_chan *); 119 120struct dw_edma_core_ops { 121 void (*off)(struct dw_edma *dw); 122 u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir); 123 enum dma_status (*ch_status)(struct dw_edma_chan *chan); 124 irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, 125 dw_edma_handler_t done, dw_edma_handler_t abort); 126 void (*start)(struct dw_edma_chunk *chunk, bool first); 127 void (*ch_config)(struct dw_edma_chan *chan); 128 void (*debugfs_on)(struct dw_edma *dw); 129}; 130 131struct dw_edma_sg { 132 struct scatterlist *sgl; 133 unsigned int len; 134}; 135 136struct dw_edma_cyclic { 137 dma_addr_t paddr; 138 size_t len; 139 size_t cnt; 140}; 141 142struct dw_edma_transfer { 143 struct dma_chan *dchan; 144 union dw_edma_xfer { 145 struct dw_edma_sg sg; 146 struct dw_edma_cyclic cyclic; 147 struct dma_interleaved_template *il; 148 } xfer; 149 enum dma_transfer_direction direction; 150 unsigned long flags; 151 enum dw_edma_xfer_type type; 152}; 153 154static inline 155struct dw_edma_chan *vc2dw_edma_chan(struct virt_dma_chan *vc) 156{ 157 return container_of(vc, struct dw_edma_chan, vc); 158} 159 160static inline 161struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan) 162{ 163 return vc2dw_edma_chan(to_virt_chan(dchan)); 164} 165 166static inline 167void dw_edma_core_off(struct dw_edma *dw) 168{ 169 dw->core->off(dw); 170} 171 172static inline 173u16 dw_edma_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir) 174{ 175 return dw->core->ch_count(dw, dir); 176} 177 178static inline 179enum dma_status dw_edma_core_ch_status(struct dw_edma_chan *chan) 180{ 181 return chan->dw->core->ch_status(chan); 182} 183 184static inline irqreturn_t 185dw_edma_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, 186 dw_edma_handler_t done, dw_edma_handler_t abort) 187{ 188 return dw_irq->dw->core->handle_int(dw_irq, dir, done, abort); 189} 190 191static inline 192void dw_edma_core_start(struct dw_edma *dw, struct dw_edma_chunk *chunk, bool first) 193{ 194 dw->core->start(chunk, first); 195} 196 197static inline 198void dw_edma_core_ch_config(struct dw_edma_chan *chan) 199{ 200 chan->dw->core->ch_config(chan); 201} 202 203static inline 204void dw_edma_core_debugfs_on(struct dw_edma *dw) 205{ 206 dw->core->debugfs_on(dw); 207} 208 209#endif /* _DW_EDMA_CORE_H */ 210