GNU Linux-libre 6.9.1-gnu
[releases.git] / drivers / dma / dw-edma / dw-edma-core.h
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 */