diff options
Diffstat (limited to 'arch/cris/arch-v32/mach-a3/dma.c')
-rw-r--r-- | arch/cris/arch-v32/mach-a3/dma.c | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/mach-a3/dma.c b/arch/cris/arch-v32/mach-a3/dma.c new file mode 100644 index 000000000000..25f236ef0b81 --- /dev/null +++ b/arch/cris/arch-v32/mach-a3/dma.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* Wrapper for DMA channel allocator that starts clocks etc */ | ||
2 | |||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/spinlock.h> | ||
5 | #include <asm/arch/mach/dma.h> | ||
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 | |||
27 | if (crisv32_arbiter_allocate_bandwidth(dmanr, | ||
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 | } | ||