Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/cris/arch-v32/mach-fs/dma.c
15125 views
1
/* Wrapper for DMA channel allocator that starts clocks etc */
2
3
#include <linux/kernel.h>
4
#include <linux/spinlock.h>
5
#include <asm/dma.h>
6
#include <hwregs/reg_map.h>
7
#include <hwregs/reg_rdwr.h>
8
#include <hwregs/marb_defs.h>
9
#include <hwregs/config_defs.h>
10
#include <hwregs/strmux_defs.h>
11
#include <linux/errno.h>
12
#include <asm/system.h>
13
#include <mach/arbiter.h>
14
15
static char used_dma_channels[MAX_DMA_CHANNELS];
16
static const char *used_dma_channels_users[MAX_DMA_CHANNELS];
17
18
static DEFINE_SPINLOCK(dma_lock);
19
20
int crisv32_request_dma(unsigned int dmanr, const char *device_id,
21
unsigned options, unsigned int bandwidth,
22
enum dma_owner owner)
23
{
24
unsigned long flags;
25
reg_config_rw_clk_ctrl clk_ctrl;
26
reg_strmux_rw_cfg strmux_cfg;
27
28
if (crisv32_arbiter_allocate_bandwidth(dmanr,
29
options & DMA_INT_MEM ?
30
INT_REGION : EXT_REGION,
31
bandwidth))
32
return -ENOMEM;
33
34
spin_lock_irqsave(&dma_lock, flags);
35
36
if (used_dma_channels[dmanr]) {
37
spin_unlock_irqrestore(&dma_lock, flags);
38
if (options & DMA_VERBOSE_ON_ERROR) {
39
printk(KERN_ERR "Failed to request DMA %i for %s, "
40
"already allocated by %s\n",
41
dmanr,
42
device_id,
43
used_dma_channels_users[dmanr]);
44
}
45
if (options & DMA_PANIC_ON_ERROR)
46
panic("request_dma error!");
47
spin_unlock_irqrestore(&dma_lock, flags);
48
return -EBUSY;
49
}
50
clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl);
51
strmux_cfg = REG_RD(strmux, regi_strmux, rw_cfg);
52
53
switch (dmanr) {
54
case 0:
55
case 1:
56
clk_ctrl.dma01_eth0 = 1;
57
break;
58
case 2:
59
case 3:
60
clk_ctrl.dma23 = 1;
61
break;
62
case 4:
63
case 5:
64
clk_ctrl.dma45 = 1;
65
break;
66
case 6:
67
case 7:
68
clk_ctrl.dma67 = 1;
69
break;
70
case 8:
71
case 9:
72
clk_ctrl.dma89_strcop = 1;
73
break;
74
#if MAX_DMA_CHANNELS-1 != 9
75
#error Check dma.c
76
#endif
77
default:
78
spin_unlock_irqrestore(&dma_lock, flags);
79
if (options & DMA_VERBOSE_ON_ERROR) {
80
printk(KERN_ERR "Failed to request DMA %i for %s, "
81
"only 0-%i valid)\n",
82
dmanr, device_id, MAX_DMA_CHANNELS - 1);
83
}
84
85
if (options & DMA_PANIC_ON_ERROR)
86
panic("request_dma error!");
87
return -EINVAL;
88
}
89
90
switch (owner) {
91
case dma_eth0:
92
if (dmanr == 0)
93
strmux_cfg.dma0 = regk_strmux_eth0;
94
else if (dmanr == 1)
95
strmux_cfg.dma1 = regk_strmux_eth0;
96
else
97
panic("Invalid DMA channel for eth0\n");
98
break;
99
case dma_eth1:
100
if (dmanr == 6)
101
strmux_cfg.dma6 = regk_strmux_eth1;
102
else if (dmanr == 7)
103
strmux_cfg.dma7 = regk_strmux_eth1;
104
else
105
panic("Invalid DMA channel for eth1\n");
106
break;
107
case dma_iop0:
108
if (dmanr == 2)
109
strmux_cfg.dma2 = regk_strmux_iop0;
110
else if (dmanr == 3)
111
strmux_cfg.dma3 = regk_strmux_iop0;
112
else
113
panic("Invalid DMA channel for iop0\n");
114
break;
115
case dma_iop1:
116
if (dmanr == 4)
117
strmux_cfg.dma4 = regk_strmux_iop1;
118
else if (dmanr == 5)
119
strmux_cfg.dma5 = regk_strmux_iop1;
120
else
121
panic("Invalid DMA channel for iop1\n");
122
break;
123
case dma_ser0:
124
if (dmanr == 6)
125
strmux_cfg.dma6 = regk_strmux_ser0;
126
else if (dmanr == 7)
127
strmux_cfg.dma7 = regk_strmux_ser0;
128
else
129
panic("Invalid DMA channel for ser0\n");
130
break;
131
case dma_ser1:
132
if (dmanr == 4)
133
strmux_cfg.dma4 = regk_strmux_ser1;
134
else if (dmanr == 5)
135
strmux_cfg.dma5 = regk_strmux_ser1;
136
else
137
panic("Invalid DMA channel for ser1\n");
138
break;
139
case dma_ser2:
140
if (dmanr == 2)
141
strmux_cfg.dma2 = regk_strmux_ser2;
142
else if (dmanr == 3)
143
strmux_cfg.dma3 = regk_strmux_ser2;
144
else
145
panic("Invalid DMA channel for ser2\n");
146
break;
147
case dma_ser3:
148
if (dmanr == 8)
149
strmux_cfg.dma8 = regk_strmux_ser3;
150
else if (dmanr == 9)
151
strmux_cfg.dma9 = regk_strmux_ser3;
152
else
153
panic("Invalid DMA channel for ser3\n");
154
break;
155
case dma_sser0:
156
if (dmanr == 4)
157
strmux_cfg.dma4 = regk_strmux_sser0;
158
else if (dmanr == 5)
159
strmux_cfg.dma5 = regk_strmux_sser0;
160
else
161
panic("Invalid DMA channel for sser0\n");
162
break;
163
case dma_sser1:
164
if (dmanr == 6)
165
strmux_cfg.dma6 = regk_strmux_sser1;
166
else if (dmanr == 7)
167
strmux_cfg.dma7 = regk_strmux_sser1;
168
else
169
panic("Invalid DMA channel for sser1\n");
170
break;
171
case dma_ata:
172
if (dmanr == 2)
173
strmux_cfg.dma2 = regk_strmux_ata;
174
else if (dmanr == 3)
175
strmux_cfg.dma3 = regk_strmux_ata;
176
else
177
panic("Invalid DMA channel for ata\n");
178
break;
179
case dma_strp:
180
if (dmanr == 8)
181
strmux_cfg.dma8 = regk_strmux_strcop;
182
else if (dmanr == 9)
183
strmux_cfg.dma9 = regk_strmux_strcop;
184
else
185
panic("Invalid DMA channel for strp\n");
186
break;
187
case dma_ext0:
188
if (dmanr == 6)
189
strmux_cfg.dma6 = regk_strmux_ext0;
190
else
191
panic("Invalid DMA channel for ext0\n");
192
break;
193
case dma_ext1:
194
if (dmanr == 7)
195
strmux_cfg.dma7 = regk_strmux_ext1;
196
else
197
panic("Invalid DMA channel for ext1\n");
198
break;
199
case dma_ext2:
200
if (dmanr == 2)
201
strmux_cfg.dma2 = regk_strmux_ext2;
202
else if (dmanr == 8)
203
strmux_cfg.dma8 = regk_strmux_ext2;
204
else
205
panic("Invalid DMA channel for ext2\n");
206
break;
207
case dma_ext3:
208
if (dmanr == 3)
209
strmux_cfg.dma3 = regk_strmux_ext3;
210
else if (dmanr == 9)
211
strmux_cfg.dma9 = regk_strmux_ext2;
212
else
213
panic("Invalid DMA channel for ext2\n");
214
break;
215
}
216
217
used_dma_channels[dmanr] = 1;
218
used_dma_channels_users[dmanr] = device_id;
219
REG_WR(config, regi_config, rw_clk_ctrl, clk_ctrl);
220
REG_WR(strmux, regi_strmux, rw_cfg, strmux_cfg);
221
spin_unlock_irqrestore(&dma_lock, flags);
222
return 0;
223
}
224
225
void crisv32_free_dma(unsigned int dmanr)
226
{
227
spin_lock(&dma_lock);
228
used_dma_channels[dmanr] = 0;
229
spin_unlock(&dma_lock);
230
}
231
232