Merge branch 'bugzilla-11312' into release
[linux-2.6] / arch / cris / arch-v32 / mach-fs / dma.c
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 }