blob: 2d970d7505c9c10d624103e3ab32d2f8493650e7 [file] [log] [blame]
Mikael Starvik51533b62005-07-27 11:44:44 -07001/* 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>
Jesper Nilsson035e1112007-11-29 17:11:23 +01006#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>
Mikael Starvik51533b62005-07-27 11:44:44 -070011#include <linux/errno.h>
12#include <asm/system.h>
Jesper Nilsson556dcee2008-10-21 17:45:58 +020013#include <mach/arbiter.h>
Mikael Starvik51533b62005-07-27 11:44:44 -070014
15static char used_dma_channels[MAX_DMA_CHANNELS];
Jesper Nilsson035e1112007-11-29 17:11:23 +010016static const char *used_dma_channels_users[MAX_DMA_CHANNELS];
Mikael Starvik51533b62005-07-27 11:44:44 -070017
18static DEFINE_SPINLOCK(dma_lock);
19
Jesper Nilsson035e1112007-11-29 17:11:23 +010020int crisv32_request_dma(unsigned int dmanr, const char *device_id,
21 unsigned options, unsigned int bandwidth,
Mikael Starvik51533b62005-07-27 11:44:44 -070022 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
Jesper Nilsson035e1112007-11-29 17:11:23 +010028 if (crisv32_arbiter_allocate_bandwidth(dmanr,
29 options & DMA_INT_MEM ?
30 INT_REGION : EXT_REGION,
31 bandwidth))
32 return -ENOMEM;
Mikael Starvik51533b62005-07-27 11:44:44 -070033
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) {
Jesper Nilsson035e1112007-11-29 17:11:23 +010039 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]);
Mikael Starvik51533b62005-07-27 11:44:44 -070044 }
45 if (options & DMA_PANIC_ON_ERROR)
46 panic("request_dma error!");
Jesper Nilsson035e1112007-11-29 17:11:23 +010047 spin_unlock_irqrestore(&dma_lock, flags);
Mikael Starvik51533b62005-07-27 11:44:44 -070048 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
Jesper Nilsson035e1112007-11-29 17:11:23 +010053 switch (dmanr) {
Mikael Starvik51533b62005-07-27 11:44:44 -070054 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) {
Jesper Nilsson035e1112007-11-29 17:11:23 +010080 printk(KERN_ERR "Failed to request DMA %i for %s, "
81 "only 0-%i valid)\n",
82 dmanr, device_id, MAX_DMA_CHANNELS - 1);
Mikael Starvik51533b62005-07-27 11:44:44 -070083 }
84
85 if (options & DMA_PANIC_ON_ERROR)
86 panic("request_dma error!");
87 return -EINVAL;
88 }
89
Jesper Nilsson035e1112007-11-29 17:11:23 +010090 switch (owner) {
Mikael Starvik51533b62005-07-27 11:44:44 -070091 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);
Jesper Nilsson035e1112007-11-29 17:11:23 +0100221 spin_unlock_irqrestore(&dma_lock, flags);
Mikael Starvik51533b62005-07-27 11:44:44 -0700222 return 0;
223}
224
225void crisv32_free_dma(unsigned int dmanr)
226{
227 spin_lock(&dma_lock);
228 used_dma_channels[dmanr] = 0;
229 spin_unlock(&dma_lock);
230}