Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/dma/txx9dmac.h
15111 views
1
/*
2
* Driver for the TXx9 SoC DMA Controller
3
*
4
* Copyright (C) 2009 Atsushi Nemoto
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
9
*/
10
#ifndef TXX9DMAC_H
11
#define TXX9DMAC_H
12
13
#include <linux/dmaengine.h>
14
#include <asm/txx9/dmac.h>
15
16
/*
17
* Design Notes:
18
*
19
* This DMAC have four channels and one FIFO buffer. Each channel can
20
* be configured for memory-memory or device-memory transfer, but only
21
* one channel can do alignment-free memory-memory transfer at a time
22
* while the channel should occupy the FIFO buffer for effective
23
* transfers.
24
*
25
* Instead of dynamically assign the FIFO buffer to channels, I chose
26
* make one dedicated channel for memory-memory transfer. The
27
* dedicated channel is public. Other channels are private and used
28
* for slave transfer. Some devices in the SoC are wired to certain
29
* DMA channel.
30
*/
31
32
#ifdef CONFIG_MACH_TX49XX
33
static inline bool txx9_dma_have_SMPCHN(void)
34
{
35
return true;
36
}
37
#define TXX9_DMA_USE_SIMPLE_CHAIN
38
#else
39
static inline bool txx9_dma_have_SMPCHN(void)
40
{
41
return false;
42
}
43
#endif
44
45
#ifdef __LITTLE_ENDIAN
46
#ifdef CONFIG_MACH_TX49XX
47
#define CCR_LE TXX9_DMA_CCR_LE
48
#define MCR_LE 0
49
#else
50
#define CCR_LE 0
51
#define MCR_LE TXX9_DMA_MCR_LE
52
#endif
53
#else
54
#define CCR_LE 0
55
#define MCR_LE 0
56
#endif
57
58
/*
59
* Redefine this macro to handle differences between 32- and 64-bit
60
* addressing, big vs. little endian, etc.
61
*/
62
#ifdef __BIG_ENDIAN
63
#define TXX9_DMA_REG32(name) u32 __pad_##name; u32 name
64
#else
65
#define TXX9_DMA_REG32(name) u32 name; u32 __pad_##name
66
#endif
67
68
/* Hardware register definitions. */
69
struct txx9dmac_cregs {
70
#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
71
TXX9_DMA_REG32(CHAR); /* Chain Address Register */
72
#else
73
u64 CHAR; /* Chain Address Register */
74
#endif
75
u64 SAR; /* Source Address Register */
76
u64 DAR; /* Destination Address Register */
77
TXX9_DMA_REG32(CNTR); /* Count Register */
78
TXX9_DMA_REG32(SAIR); /* Source Address Increment Register */
79
TXX9_DMA_REG32(DAIR); /* Destination Address Increment Register */
80
TXX9_DMA_REG32(CCR); /* Channel Control Register */
81
TXX9_DMA_REG32(CSR); /* Channel Status Register */
82
};
83
struct txx9dmac_cregs32 {
84
u32 CHAR;
85
u32 SAR;
86
u32 DAR;
87
u32 CNTR;
88
u32 SAIR;
89
u32 DAIR;
90
u32 CCR;
91
u32 CSR;
92
};
93
94
struct txx9dmac_regs {
95
/* per-channel registers */
96
struct txx9dmac_cregs CHAN[TXX9_DMA_MAX_NR_CHANNELS];
97
u64 __pad[9];
98
u64 MFDR; /* Memory Fill Data Register */
99
TXX9_DMA_REG32(MCR); /* Master Control Register */
100
};
101
struct txx9dmac_regs32 {
102
struct txx9dmac_cregs32 CHAN[TXX9_DMA_MAX_NR_CHANNELS];
103
u32 __pad[9];
104
u32 MFDR;
105
u32 MCR;
106
};
107
108
/* bits for MCR */
109
#define TXX9_DMA_MCR_EIS(ch) (0x10000000<<(ch))
110
#define TXX9_DMA_MCR_DIS(ch) (0x01000000<<(ch))
111
#define TXX9_DMA_MCR_RSFIF 0x00000080
112
#define TXX9_DMA_MCR_FIFUM(ch) (0x00000008<<(ch))
113
#define TXX9_DMA_MCR_LE 0x00000004
114
#define TXX9_DMA_MCR_RPRT 0x00000002
115
#define TXX9_DMA_MCR_MSTEN 0x00000001
116
117
/* bits for CCRn */
118
#define TXX9_DMA_CCR_IMMCHN 0x20000000
119
#define TXX9_DMA_CCR_USEXFSZ 0x10000000
120
#define TXX9_DMA_CCR_LE 0x08000000
121
#define TXX9_DMA_CCR_DBINH 0x04000000
122
#define TXX9_DMA_CCR_SBINH 0x02000000
123
#define TXX9_DMA_CCR_CHRST 0x01000000
124
#define TXX9_DMA_CCR_RVBYTE 0x00800000
125
#define TXX9_DMA_CCR_ACKPOL 0x00400000
126
#define TXX9_DMA_CCR_REQPL 0x00200000
127
#define TXX9_DMA_CCR_EGREQ 0x00100000
128
#define TXX9_DMA_CCR_CHDN 0x00080000
129
#define TXX9_DMA_CCR_DNCTL 0x00060000
130
#define TXX9_DMA_CCR_EXTRQ 0x00010000
131
#define TXX9_DMA_CCR_INTRQD 0x0000e000
132
#define TXX9_DMA_CCR_INTENE 0x00001000
133
#define TXX9_DMA_CCR_INTENC 0x00000800
134
#define TXX9_DMA_CCR_INTENT 0x00000400
135
#define TXX9_DMA_CCR_CHNEN 0x00000200
136
#define TXX9_DMA_CCR_XFACT 0x00000100
137
#define TXX9_DMA_CCR_SMPCHN 0x00000020
138
#define TXX9_DMA_CCR_XFSZ(order) (((order) << 2) & 0x0000001c)
139
#define TXX9_DMA_CCR_XFSZ_1 TXX9_DMA_CCR_XFSZ(0)
140
#define TXX9_DMA_CCR_XFSZ_2 TXX9_DMA_CCR_XFSZ(1)
141
#define TXX9_DMA_CCR_XFSZ_4 TXX9_DMA_CCR_XFSZ(2)
142
#define TXX9_DMA_CCR_XFSZ_8 TXX9_DMA_CCR_XFSZ(3)
143
#define TXX9_DMA_CCR_XFSZ_X4 TXX9_DMA_CCR_XFSZ(4)
144
#define TXX9_DMA_CCR_XFSZ_X8 TXX9_DMA_CCR_XFSZ(5)
145
#define TXX9_DMA_CCR_XFSZ_X16 TXX9_DMA_CCR_XFSZ(6)
146
#define TXX9_DMA_CCR_XFSZ_X32 TXX9_DMA_CCR_XFSZ(7)
147
#define TXX9_DMA_CCR_MEMIO 0x00000002
148
#define TXX9_DMA_CCR_SNGAD 0x00000001
149
150
/* bits for CSRn */
151
#define TXX9_DMA_CSR_CHNEN 0x00000400
152
#define TXX9_DMA_CSR_STLXFER 0x00000200
153
#define TXX9_DMA_CSR_XFACT 0x00000100
154
#define TXX9_DMA_CSR_ABCHC 0x00000080
155
#define TXX9_DMA_CSR_NCHNC 0x00000040
156
#define TXX9_DMA_CSR_NTRNFC 0x00000020
157
#define TXX9_DMA_CSR_EXTDN 0x00000010
158
#define TXX9_DMA_CSR_CFERR 0x00000008
159
#define TXX9_DMA_CSR_CHERR 0x00000004
160
#define TXX9_DMA_CSR_DESERR 0x00000002
161
#define TXX9_DMA_CSR_SORERR 0x00000001
162
163
struct txx9dmac_chan {
164
struct dma_chan chan;
165
struct dma_device dma;
166
struct txx9dmac_dev *ddev;
167
void __iomem *ch_regs;
168
struct tasklet_struct tasklet;
169
int irq;
170
u32 ccr;
171
172
spinlock_t lock;
173
174
/* these other elements are all protected by lock */
175
dma_cookie_t completed;
176
struct list_head active_list;
177
struct list_head queue;
178
struct list_head free_list;
179
180
unsigned int descs_allocated;
181
};
182
183
struct txx9dmac_dev {
184
void __iomem *regs;
185
struct tasklet_struct tasklet;
186
int irq;
187
struct txx9dmac_chan *chan[TXX9_DMA_MAX_NR_CHANNELS];
188
bool have_64bit_regs;
189
unsigned int descsize;
190
};
191
192
static inline bool __is_dmac64(const struct txx9dmac_dev *ddev)
193
{
194
return ddev->have_64bit_regs;
195
}
196
197
static inline bool is_dmac64(const struct txx9dmac_chan *dc)
198
{
199
return __is_dmac64(dc->ddev);
200
}
201
202
#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
203
/* Hardware descriptor definition. (for simple-chain) */
204
struct txx9dmac_hwdesc {
205
#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
206
TXX9_DMA_REG32(CHAR);
207
#else
208
u64 CHAR;
209
#endif
210
u64 SAR;
211
u64 DAR;
212
TXX9_DMA_REG32(CNTR);
213
};
214
struct txx9dmac_hwdesc32 {
215
u32 CHAR;
216
u32 SAR;
217
u32 DAR;
218
u32 CNTR;
219
};
220
#else
221
#define txx9dmac_hwdesc txx9dmac_cregs
222
#define txx9dmac_hwdesc32 txx9dmac_cregs32
223
#endif
224
225
struct txx9dmac_desc {
226
/* FIRST values the hardware uses */
227
union {
228
struct txx9dmac_hwdesc hwdesc;
229
struct txx9dmac_hwdesc32 hwdesc32;
230
};
231
232
/* THEN values for driver housekeeping */
233
struct list_head desc_node ____cacheline_aligned;
234
struct list_head tx_list;
235
struct dma_async_tx_descriptor txd;
236
size_t len;
237
};
238
239
#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
240
241
static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
242
{
243
return (dc->ccr & TXX9_DMA_CCR_INTENT) != 0;
244
}
245
246
static inline void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
247
{
248
dc->ccr |= TXX9_DMA_CCR_INTENT;
249
}
250
251
static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
252
struct txx9dmac_desc *desc)
253
{
254
}
255
256
static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
257
{
258
dc->ccr |= TXX9_DMA_CCR_SMPCHN;
259
}
260
261
static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
262
struct txx9dmac_desc *desc,
263
u32 sair, u32 dair, u32 ccr)
264
{
265
}
266
267
#else /* TXX9_DMA_USE_SIMPLE_CHAIN */
268
269
static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
270
{
271
return true;
272
}
273
274
static void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
275
{
276
}
277
278
static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
279
struct txx9dmac_desc *desc)
280
{
281
if (__is_dmac64(ddev))
282
desc->hwdesc.CCR |= TXX9_DMA_CCR_INTENT;
283
else
284
desc->hwdesc32.CCR |= TXX9_DMA_CCR_INTENT;
285
}
286
287
static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
288
{
289
}
290
291
static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
292
struct txx9dmac_desc *desc,
293
u32 sai, u32 dai, u32 ccr)
294
{
295
if (__is_dmac64(ddev)) {
296
desc->hwdesc.SAIR = sai;
297
desc->hwdesc.DAIR = dai;
298
desc->hwdesc.CCR = ccr;
299
} else {
300
desc->hwdesc32.SAIR = sai;
301
desc->hwdesc32.DAIR = dai;
302
desc->hwdesc32.CCR = ccr;
303
}
304
}
305
306
#endif /* TXX9_DMA_USE_SIMPLE_CHAIN */
307
308
#endif /* TXX9DMAC_H */
309
310