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 }; 90 91 struct dw_edma_irq { 92 struct msi_msg msi; 93 u32 wr_mask; 94 u32 rd_mask; 95 struct dw_edma *dw; 96 }; 97 98 struct 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 118 typedef void (*dw_edma_handler_t)(struct dw_edma_chan *); 119 120 struct 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 131 struct dw_edma_sg { 132 struct scatterlist *sgl; 133 unsigned int len; 134 }; 135 136 struct dw_edma_cyclic { 137 dma_addr_t paddr; 138 size_t len; 139 size_t cnt; 140 }; 141 142 struct 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 154 static inline 155 struct dw_edma_chan *vc2dw_edma_chan(struct virt_dma_chan *vc) 156 { 157 return container_of(vc, struct dw_edma_chan, vc); 158 } 159 160 static inline 161 struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan) 162 { 163 return vc2dw_edma_chan(to_virt_chan(dchan)); 164 } 165 166 static inline 167 void dw_edma_core_off(struct dw_edma *dw) 168 { 169 dw->core->off(dw); 170 } 171 172 static inline 173 u16 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 178 static inline 179 enum dma_status dw_edma_core_ch_status(struct dw_edma_chan *chan) 180 { 181 return chan->dw->core->ch_status(chan); 182 } 183 184 static inline irqreturn_t 185 dw_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 191 static inline 192 void dw_edma_core_start(struct dw_edma *dw, struct dw_edma_chunk *chunk, bool first) 193 { 194 dw->core->start(chunk, first); 195 } 196 197 static inline 198 void dw_edma_core_ch_config(struct dw_edma_chan *chan) 199 { 200 chan->dw->core->ch_config(chan); 201 } 202 203 static inline 204 void 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