hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
 * Synopsys DesignWare eDMA core driver
 *
 * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
 */
 
#ifndef _DW_EDMA_CORE_H
#define _DW_EDMA_CORE_H
 
#include <linux/msi.h>
#include <linux/dma/edma.h>
 
#include "../virt-dma.h"
 
#define EDMA_LL_SZ                    24
 
enum dw_edma_dir {
   EDMA_DIR_WRITE = 0,
   EDMA_DIR_READ
};
 
enum dw_edma_mode {
   EDMA_MODE_LEGACY = 0,
   EDMA_MODE_UNROLL
};
 
enum dw_edma_request {
   EDMA_REQ_NONE = 0,
   EDMA_REQ_STOP,
   EDMA_REQ_PAUSE
};
 
enum dw_edma_status {
   EDMA_ST_IDLE = 0,
   EDMA_ST_PAUSE,
   EDMA_ST_BUSY
};
 
struct dw_edma_chan;
struct dw_edma_chunk;
 
struct dw_edma_burst {
   struct list_head        list;
   u64                sar;
   u64                dar;
   u32                sz;
};
 
struct dw_edma_region {
   phys_addr_t            paddr;
   void                __iomem *vaddr;
   size_t                sz;
};
 
struct dw_edma_chunk {
   struct list_head        list;
   struct dw_edma_chan        *chan;
   struct dw_edma_burst        *burst;
 
   u32                bursts_alloc;
 
   u8                cb;
   struct dw_edma_region        ll_region;    /* Linked list */
};
 
struct dw_edma_desc {
   struct virt_dma_desc        vd;
   struct dw_edma_chan        *chan;
   struct dw_edma_chunk        *chunk;
 
   u32                chunks_alloc;
 
   u32                alloc_sz;
   u32                xfer_sz;
};
 
struct dw_edma_chan {
   struct virt_dma_chan        vc;
   struct dw_edma_chip        *chip;
   int                id;
   enum dw_edma_dir        dir;
 
   off_t                ll_off;
   u32                ll_max;
 
   off_t                dt_off;
 
   struct msi_msg            msi;
 
   enum dw_edma_request        request;
   enum dw_edma_status        status;
   u8                configured;
 
   struct dma_slave_config        config;
};
 
struct dw_edma_irq {
   struct msi_msg                  msi;
   u32                wr_mask;
   u32                rd_mask;
   struct dw_edma            *dw;
};
 
struct dw_edma_core_ops {
   int    (*irq_vector)(struct device *dev, unsigned int nr);
};
 
struct dw_edma {
   char                name[20];
 
   struct dma_device        wr_edma;
   u16                wr_ch_cnt;
 
   struct dma_device        rd_edma;
   u16                rd_ch_cnt;
 
   struct dw_edma_region        rg_region;    /* Registers */
   struct dw_edma_region        ll_region;    /* Linked list */
   struct dw_edma_region        dt_region;    /* Data */
 
   struct dw_edma_irq        *irq;
   int                nr_irqs;
 
   u32                version;
   enum dw_edma_mode        mode;
 
   struct dw_edma_chan        *chan;
   const struct dw_edma_core_ops    *ops;
 
   raw_spinlock_t            lock;        /* Only for legacy */
};
 
struct dw_edma_sg {
   struct scatterlist        *sgl;
   unsigned int            len;
};
 
struct dw_edma_cyclic {
   dma_addr_t            paddr;
   size_t                len;
   size_t                cnt;
};
 
struct dw_edma_transfer {
   struct dma_chan            *dchan;
   union dw_edma_xfer {
       struct dw_edma_sg    sg;
       struct dw_edma_cyclic    cyclic;
   } xfer;
   enum dma_transfer_direction    direction;
   unsigned long            flags;
   bool                cyclic;
};
 
static inline
struct dw_edma_chan *vc2dw_edma_chan(struct virt_dma_chan *vc)
{
   return container_of(vc, struct dw_edma_chan, vc);
}
 
static inline
struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan)
{
   return vc2dw_edma_chan(to_virt_chan(dchan));
}
 
#endif /* _DW_EDMA_CORE_H */