Commit | Line | Data |
---|---|---|
035e111f JN |
1 | /* Wrapper for DMA channel allocator that starts clocks etc */ |
2 | ||
3 | #include <linux/kernel.h> | |
4 | #include <linux/spinlock.h> | |
556dcee7 | 5 | #include <mach/dma.h> |
035e111f JN |
6 | #include <hwregs/reg_map.h> |
7 | #include <hwregs/reg_rdwr.h> | |
8 | #include <hwregs/marb_defs.h> | |
9 | #include <hwregs/clkgen_defs.h> | |
10 | #include <hwregs/strmux_defs.h> | |
11 | #include <linux/errno.h> | |
12 | #include <asm/system.h> | |
13 | #include <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, enum dma_owner owner) | |
22 | { | |
23 | unsigned long flags; | |
24 | reg_clkgen_rw_clk_ctrl clk_ctrl; | |
25 | reg_strmux_rw_cfg strmux_cfg; | |
26 | ||
eb090473 | 27 | if (crisv32_arbiter_allocate_bandwidth(dmanr, |
035e111f JN |
28 | options & DMA_INT_MEM ? INT_REGION : EXT_REGION, |
29 | bandwidth)) | |
30 | return -ENOMEM; | |
31 | ||
32 | spin_lock_irqsave(&dma_lock, flags); | |
33 | ||
34 | if (used_dma_channels[dmanr]) { | |
35 | spin_unlock_irqrestore(&dma_lock, flags); | |
36 | if (options & DMA_VERBOSE_ON_ERROR) | |
37 | printk(KERN_ERR "Failed to request DMA %i for %s, " | |
38 | "already allocated by %s\n", | |
39 | dmanr, | |
40 | device_id, | |
41 | used_dma_channels_users[dmanr]); | |
42 | ||
43 | if (options & DMA_PANIC_ON_ERROR) | |
44 | panic("request_dma error!"); | |
45 | spin_unlock_irqrestore(&dma_lock, flags); | |
46 | return -EBUSY; | |
47 | } | |
48 | clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); | |
49 | strmux_cfg = REG_RD(strmux, regi_strmux, rw_cfg); | |
50 | ||
51 | switch (dmanr) { | |
52 | case 0: | |
53 | case 1: | |
54 | clk_ctrl.dma0_1_eth = 1; | |
55 | break; | |
56 | case 2: | |
57 | case 3: | |
58 | clk_ctrl.dma2_3_strcop = 1; | |
59 | break; | |
60 | case 4: | |
61 | case 5: | |
62 | clk_ctrl.dma4_5_iop = 1; | |
63 | break; | |
64 | case 6: | |
65 | case 7: | |
66 | clk_ctrl.sser_ser_dma6_7 = 1; | |
67 | break; | |
68 | case 9: | |
69 | case 11: | |
70 | clk_ctrl.dma9_11 = 1; | |
71 | break; | |
72 | #if MAX_DMA_CHANNELS-1 != 11 | |
73 | #error Check dma.c | |
74 | #endif | |
75 | default: | |
76 | spin_unlock_irqrestore(&dma_lock, flags); | |
77 | if (options & DMA_VERBOSE_ON_ERROR) | |
78 | printk(KERN_ERR "Failed to request DMA %i for %s, " | |
79 | "only 0-%i valid)\n", | |
80 | dmanr, device_id, MAX_DMA_CHANNELS-1); | |
81 | ||
82 | if (options & DMA_PANIC_ON_ERROR) | |
83 | panic("request_dma error!"); | |
84 | return -EINVAL; | |
85 | } | |
86 | ||
87 | switch (owner) { | |
88 | case dma_eth: | |
89 | if (dmanr == 0) | |
90 | strmux_cfg.dma0 = regk_strmux_eth; | |
91 | else if (dmanr == 1) | |
92 | strmux_cfg.dma1 = regk_strmux_eth; | |
93 | else | |
94 | panic("Invalid DMA channel for eth\n"); | |
95 | break; | |
96 | case dma_ser0: | |
97 | if (dmanr == 0) | |
98 | strmux_cfg.dma0 = regk_strmux_ser0; | |
99 | else if (dmanr == 1) | |
100 | strmux_cfg.dma1 = regk_strmux_ser0; | |
101 | else | |
102 | panic("Invalid DMA channel for ser0\n"); | |
103 | break; | |
104 | case dma_ser3: | |
105 | if (dmanr == 2) | |
106 | strmux_cfg.dma2 = regk_strmux_ser3; | |
107 | else if (dmanr == 3) | |
108 | strmux_cfg.dma3 = regk_strmux_ser3; | |
109 | else | |
110 | panic("Invalid DMA channel for ser3\n"); | |
111 | break; | |
112 | case dma_strp: | |
113 | if (dmanr == 2) | |
114 | strmux_cfg.dma2 = regk_strmux_strcop; | |
115 | else if (dmanr == 3) | |
116 | strmux_cfg.dma3 = regk_strmux_strcop; | |
117 | else | |
118 | panic("Invalid DMA channel for strp\n"); | |
119 | break; | |
120 | case dma_ser1: | |
121 | if (dmanr == 4) | |
122 | strmux_cfg.dma4 = regk_strmux_ser1; | |
123 | else if (dmanr == 5) | |
124 | strmux_cfg.dma5 = regk_strmux_ser1; | |
125 | else | |
126 | panic("Invalid DMA channel for ser1\n"); | |
127 | break; | |
128 | case dma_iop: | |
129 | if (dmanr == 4) | |
130 | strmux_cfg.dma4 = regk_strmux_iop; | |
131 | else if (dmanr == 5) | |
132 | strmux_cfg.dma5 = regk_strmux_iop; | |
133 | else | |
134 | panic("Invalid DMA channel for iop\n"); | |
135 | break; | |
136 | case dma_ser2: | |
137 | if (dmanr == 6) | |
138 | strmux_cfg.dma6 = regk_strmux_ser2; | |
139 | else if (dmanr == 7) | |
140 | strmux_cfg.dma7 = regk_strmux_ser2; | |
141 | else | |
142 | panic("Invalid DMA channel for ser2\n"); | |
143 | break; | |
144 | case dma_sser: | |
145 | if (dmanr == 6) | |
146 | strmux_cfg.dma6 = regk_strmux_sser; | |
147 | else if (dmanr == 7) | |
148 | strmux_cfg.dma7 = regk_strmux_sser; | |
149 | else | |
150 | panic("Invalid DMA channel for sser\n"); | |
151 | break; | |
152 | case dma_ser4: | |
153 | if (dmanr == 9) | |
154 | strmux_cfg.dma9 = regk_strmux_ser4; | |
155 | else | |
156 | panic("Invalid DMA channel for ser4\n"); | |
157 | break; | |
158 | case dma_jpeg: | |
159 | if (dmanr == 9) | |
160 | strmux_cfg.dma9 = regk_strmux_jpeg; | |
161 | else | |
162 | panic("Invalid DMA channel for JPEG\n"); | |
163 | break; | |
164 | case dma_h264: | |
165 | if (dmanr == 11) | |
166 | strmux_cfg.dma11 = regk_strmux_h264; | |
167 | else | |
168 | panic("Invalid DMA channel for H264\n"); | |
169 | break; | |
170 | } | |
171 | ||
172 | used_dma_channels[dmanr] = 1; | |
173 | used_dma_channels_users[dmanr] = device_id; | |
174 | REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl); | |
175 | REG_WR(strmux, regi_strmux, rw_cfg, strmux_cfg); | |
176 | spin_unlock_irqrestore(&dma_lock, flags); | |
177 | return 0; | |
178 | } | |
179 | ||
180 | void crisv32_free_dma(unsigned int dmanr) | |
181 | { | |
182 | spin_lock(&dma_lock); | |
183 | used_dma_channels[dmanr] = 0; | |
184 | spin_unlock(&dma_lock); | |
185 | } |