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 19 enum dw_edma_dir { 20 EDMA_DIR_WRITE = 0, 21 EDMA_DIR_READ 22 }; 23 24 enum dw_edma_request { 25 EDMA_REQ_NONE = 0, 26 EDMA_REQ_STOP, 27 EDMA_REQ_PAUSE 28 }; 29 30 enum dw_edma_status { 31 EDMA_ST_IDLE = 0, 32 EDMA_ST_PAUSE, 33 EDMA_ST_BUSY 34 }; 35 36 enum dw_edma_xfer_type { 37 EDMA_XFER_SCATTER_GATHER = 0, 38 EDMA_XFER_CYCLIC, 39 EDMA_XFER_INTERLEAVED 40 }; 41 42 struct dw_edma_chan; 43 struct dw_edma_chunk; 44 45 struct dw_edma_burst { 46 struct list_head list; 47 u64 sar; 48 u64 dar; 49 u32 sz; 50 }; 51 52 struct 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 63 struct 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 74 struct 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 bool non_ll; 90 }; 91 92 struct dw_edma_irq { 93 struct msi_msg msi; 94 u32 wr_mask; 95 u32 rd_mask; 96 struct dw_edma *dw; 97 }; 98 99 struct dw_edma { 100 char name[32]; 101 102 struct dma_device dma; 103 104 u16 wr_ch_cnt; 105 u16 rd_ch_cnt; 106 107 struct dw_edma_irq *irq; 108 int nr_irqs; 109 110 struct dw_edma_chan *chan; 111 112 raw_spinlock_t lock; /* Only for legacy */ 113 114 struct dw_edma_chip *chip; 115 116 const struct dw_edma_core_ops *core; 117 }; 118 119 typedef void (*dw_edma_handler_t)(struct dw_edma_chan *); 120 121 struct dw_edma_core_ops { 122 void (*off)(struct dw_edma *dw); 123 u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir); 124 enum dma_status (*ch_status)(struct dw_edma_chan *chan); 125 irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, 126 dw_edma_handler_t done, dw_edma_handler_t abort); 127 void (*start)(struct dw_edma_chunk *chunk, bool first); 128 void (*ch_config)(struct dw_edma_chan *chan); 129 void (*debugfs_on)(struct dw_edma *dw); 130 void (*ack_emulated_irq)(struct dw_edma *dw); 131 resource_size_t (*db_offset)(struct dw_edma *dw); 132 }; 133 134 struct dw_edma_sg { 135 struct scatterlist *sgl; 136 unsigned int len; 137 }; 138 139 struct dw_edma_cyclic { 140 dma_addr_t paddr; 141 size_t len; 142 size_t cnt; 143 }; 144 145 struct dw_edma_transfer { 146 struct dma_chan *dchan; 147 union dw_edma_xfer { 148 struct dw_edma_sg sg; 149 struct dw_edma_cyclic cyclic; 150 struct dma_interleaved_template *il; 151 } xfer; 152 enum dma_transfer_direction direction; 153 unsigned long flags; 154 enum dw_edma_xfer_type type; 155 }; 156 157 static inline 158 struct dw_edma_chan *vc2dw_edma_chan(struct virt_dma_chan *vc) 159 { 160 return container_of(vc, struct dw_edma_chan, vc); 161 } 162 163 static inline 164 struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan) 165 { 166 return vc2dw_edma_chan(to_virt_chan(dchan)); 167 } 168 169 static inline 170 void dw_edma_core_off(struct dw_edma *dw) 171 { 172 dw->core->off(dw); 173 } 174 175 static inline 176 u16 dw_edma_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir) 177 { 178 return dw->core->ch_count(dw, dir); 179 } 180 181 static inline 182 enum dma_status dw_edma_core_ch_status(struct dw_edma_chan *chan) 183 { 184 return chan->dw->core->ch_status(chan); 185 } 186 187 static inline irqreturn_t 188 dw_edma_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, 189 dw_edma_handler_t done, dw_edma_handler_t abort) 190 { 191 return dw_irq->dw->core->handle_int(dw_irq, dir, done, abort); 192 } 193 194 static inline 195 void dw_edma_core_start(struct dw_edma *dw, struct dw_edma_chunk *chunk, bool first) 196 { 197 dw->core->start(chunk, first); 198 } 199 200 static inline 201 void dw_edma_core_ch_config(struct dw_edma_chan *chan) 202 { 203 chan->dw->core->ch_config(chan); 204 } 205 206 static inline 207 void dw_edma_core_debugfs_on(struct dw_edma *dw) 208 { 209 dw->core->debugfs_on(dw); 210 } 211 212 static inline int dw_edma_core_ack_emulated_irq(struct dw_edma *dw) 213 { 214 if (!dw->core->ack_emulated_irq) 215 return -EOPNOTSUPP; 216 217 dw->core->ack_emulated_irq(dw); 218 return 0; 219 } 220 221 static inline resource_size_t 222 dw_edma_core_db_offset(struct dw_edma *dw) 223 { 224 return dw->core->db_offset(dw); 225 } 226 227 #endif /* _DW_EDMA_CORE_H */ 228