Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * BRIEF MODULE DESCRIPTION | |
ff6814d5 SS |
3 | * Defines for using and allocating DMA channels on the Alchemy |
4 | * Au1x00 MIPS processors. | |
1da177e4 | 5 | * |
ff6814d5 SS |
6 | * Copyright 2000, 2008 MontaVista Software Inc. |
7 | * Author: MontaVista Software, Inc. <source@mvista.com> | |
1da177e4 LT |
8 | * |
9 | * This program is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public License as published by the | |
11 | * Free Software Foundation; either version 2 of the License, or (at your | |
12 | * option) any later version. | |
13 | * | |
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
16 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | |
17 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
20 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | * | |
25 | * You should have received a copy of the GNU General Public License along | |
26 | * with this program; if not, write to the Free Software Foundation, Inc., | |
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | |
28 | * | |
29 | */ | |
30 | #ifndef __ASM_AU1000_DMA_H | |
31 | #define __ASM_AU1000_DMA_H | |
32 | ||
ff6814d5 | 33 | #include <linux/io.h> /* need byte IO */ |
1da177e4 LT |
34 | #include <linux/spinlock.h> /* And spinlocks */ |
35 | #include <linux/delay.h> | |
1da177e4 | 36 | |
70342287 | 37 | #define NUM_AU1000_DMA_CHANNELS 8 |
1da177e4 | 38 | |
1da177e4 LT |
39 | /* DMA Channel Register Offsets */ |
40 | #define DMA_MODE_SET 0x00000000 | |
41 | #define DMA_MODE_READ DMA_MODE_SET | |
42 | #define DMA_MODE_CLEAR 0x00000004 | |
43 | /* DMA Mode register bits follow */ | |
44 | #define DMA_DAH_MASK (0x0f << 20) | |
45 | #define DMA_DID_BIT 16 | |
46 | #define DMA_DID_MASK (0x0f << DMA_DID_BIT) | |
ff6814d5 SS |
47 | #define DMA_DS (1 << 15) |
48 | #define DMA_BE (1 << 13) | |
49 | #define DMA_DR (1 << 12) | |
70342287 | 50 | #define DMA_TS8 (1 << 11) |
1da177e4 LT |
51 | #define DMA_DW_BIT 9 |
52 | #define DMA_DW_MASK (0x03 << DMA_DW_BIT) | |
53 | #define DMA_DW8 (0 << DMA_DW_BIT) | |
54 | #define DMA_DW16 (1 << DMA_DW_BIT) | |
55 | #define DMA_DW32 (2 << DMA_DW_BIT) | |
ff6814d5 SS |
56 | #define DMA_NC (1 << 8) |
57 | #define DMA_IE (1 << 7) | |
58 | #define DMA_HALT (1 << 6) | |
59 | #define DMA_GO (1 << 5) | |
60 | #define DMA_AB (1 << 4) | |
61 | #define DMA_D1 (1 << 3) | |
70342287 | 62 | #define DMA_BE1 (1 << 2) |
ff6814d5 | 63 | #define DMA_D0 (1 << 1) |
70342287 | 64 | #define DMA_BE0 (1 << 0) |
ff6814d5 SS |
65 | |
66 | #define DMA_PERIPHERAL_ADDR 0x00000008 | |
67 | #define DMA_BUFFER0_START 0x0000000C | |
68 | #define DMA_BUFFER1_START 0x00000014 | |
69 | #define DMA_BUFFER0_COUNT 0x00000010 | |
70 | #define DMA_BUFFER1_COUNT 0x00000018 | |
71 | #define DMA_BAH_BIT 16 | |
72 | #define DMA_BAH_MASK (0x0f << DMA_BAH_BIT) | |
73 | #define DMA_COUNT_BIT 0 | |
74 | #define DMA_COUNT_MASK (0xffff << DMA_COUNT_BIT) | |
75 | ||
76 | /* DMA Device IDs follow */ | |
1da177e4 LT |
77 | enum { |
78 | DMA_ID_UART0_TX = 0, | |
79 | DMA_ID_UART0_RX, | |
80 | DMA_ID_GP04, | |
81 | DMA_ID_GP05, | |
82 | DMA_ID_AC97C_TX, | |
83 | DMA_ID_AC97C_RX, | |
84 | DMA_ID_UART3_TX, | |
85 | DMA_ID_UART3_RX, | |
86 | DMA_ID_USBDEV_EP0_RX, | |
87 | DMA_ID_USBDEV_EP0_TX, | |
88 | DMA_ID_USBDEV_EP2_TX, | |
89 | DMA_ID_USBDEV_EP3_TX, | |
90 | DMA_ID_USBDEV_EP4_RX, | |
91 | DMA_ID_USBDEV_EP5_RX, | |
92 | DMA_ID_I2S_TX, | |
93 | DMA_ID_I2S_RX, | |
94 | DMA_NUM_DEV | |
95 | }; | |
96 | ||
97 | /* DMA Device ID's for 2nd bank (AU1100) follow */ | |
98 | enum { | |
99 | DMA_ID_SD0_TX = 0, | |
100 | DMA_ID_SD0_RX, | |
101 | DMA_ID_SD1_TX, | |
102 | DMA_ID_SD1_RX, | |
103 | DMA_NUM_DEV_BANK2 | |
104 | }; | |
105 | ||
106 | struct dma_chan { | |
ff6814d5 SS |
107 | int dev_id; /* this channel is allocated if >= 0, */ |
108 | /* free otherwise */ | |
1da177e4 LT |
109 | unsigned int io; |
110 | const char *dev_str; | |
111 | int irq; | |
112 | void *irq_dev; | |
113 | unsigned int fifo_addr; | |
114 | unsigned int mode; | |
115 | }; | |
116 | ||
117 | /* These are in arch/mips/au1000/common/dma.c */ | |
118 | extern struct dma_chan au1000_dma_table[]; | |
119 | extern int request_au1000_dma(int dev_id, | |
120 | const char *dev_str, | |
40220c1a | 121 | irq_handler_t irqhandler, |
1da177e4 LT |
122 | unsigned long irqflags, |
123 | void *irq_dev_id); | |
124 | extern void free_au1000_dma(unsigned int dmanr); | |
125 | extern int au1000_dma_read_proc(char *buf, char **start, off_t fpos, | |
126 | int length, int *eof, void *data); | |
127 | extern void dump_au1000_dma_channel(unsigned int dmanr); | |
128 | extern spinlock_t au1000_dma_spin_lock; | |
129 | ||
ff6814d5 | 130 | static inline struct dma_chan *get_dma_chan(unsigned int dmanr) |
1da177e4 | 131 | { |
ff6814d5 SS |
132 | if (dmanr >= NUM_AU1000_DMA_CHANNELS || |
133 | au1000_dma_table[dmanr].dev_id < 0) | |
1da177e4 LT |
134 | return NULL; |
135 | return &au1000_dma_table[dmanr]; | |
136 | } | |
137 | ||
ff6814d5 | 138 | static inline unsigned long claim_dma_lock(void) |
1da177e4 LT |
139 | { |
140 | unsigned long flags; | |
ff6814d5 | 141 | |
1da177e4 LT |
142 | spin_lock_irqsave(&au1000_dma_spin_lock, flags); |
143 | return flags; | |
144 | } | |
145 | ||
ff6814d5 | 146 | static inline void release_dma_lock(unsigned long flags) |
1da177e4 LT |
147 | { |
148 | spin_unlock_irqrestore(&au1000_dma_spin_lock, flags); | |
149 | } | |
150 | ||
151 | /* | |
152 | * Set the DMA buffer enable bits in the mode register. | |
153 | */ | |
ff6814d5 | 154 | static inline void enable_dma_buffer0(unsigned int dmanr) |
1da177e4 LT |
155 | { |
156 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 157 | |
1da177e4 LT |
158 | if (!chan) |
159 | return; | |
160 | au_writel(DMA_BE0, chan->io + DMA_MODE_SET); | |
161 | } | |
ff6814d5 SS |
162 | |
163 | static inline void enable_dma_buffer1(unsigned int dmanr) | |
1da177e4 LT |
164 | { |
165 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 166 | |
1da177e4 LT |
167 | if (!chan) |
168 | return; | |
169 | au_writel(DMA_BE1, chan->io + DMA_MODE_SET); | |
170 | } | |
ff6814d5 | 171 | static inline void enable_dma_buffers(unsigned int dmanr) |
1da177e4 LT |
172 | { |
173 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 174 | |
1da177e4 LT |
175 | if (!chan) |
176 | return; | |
177 | au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET); | |
178 | } | |
179 | ||
ff6814d5 | 180 | static inline void start_dma(unsigned int dmanr) |
1da177e4 LT |
181 | { |
182 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 183 | |
1da177e4 LT |
184 | if (!chan) |
185 | return; | |
1da177e4 LT |
186 | au_writel(DMA_GO, chan->io + DMA_MODE_SET); |
187 | } | |
188 | ||
189 | #define DMA_HALT_POLL 0x5000 | |
190 | ||
ff6814d5 | 191 | static inline void halt_dma(unsigned int dmanr) |
1da177e4 LT |
192 | { |
193 | struct dma_chan *chan = get_dma_chan(dmanr); | |
194 | int i; | |
ff6814d5 | 195 | |
1da177e4 LT |
196 | if (!chan) |
197 | return; | |
1da177e4 | 198 | au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR); |
ff6814d5 SS |
199 | |
200 | /* Poll the halt bit */ | |
1da177e4 LT |
201 | for (i = 0; i < DMA_HALT_POLL; i++) |
202 | if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) | |
203 | break; | |
204 | if (i == DMA_HALT_POLL) | |
205 | printk(KERN_INFO "halt_dma: HALT poll expired!\n"); | |
206 | } | |
207 | ||
ff6814d5 | 208 | static inline void disable_dma(unsigned int dmanr) |
1da177e4 LT |
209 | { |
210 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 211 | |
1da177e4 LT |
212 | if (!chan) |
213 | return; | |
214 | ||
215 | halt_dma(dmanr); | |
216 | ||
ff6814d5 | 217 | /* Now we can disable the buffers */ |
1da177e4 LT |
218 | au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR); |
219 | } | |
220 | ||
ff6814d5 | 221 | static inline int dma_halted(unsigned int dmanr) |
1da177e4 LT |
222 | { |
223 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 224 | |
1da177e4 LT |
225 | if (!chan) |
226 | return 1; | |
227 | return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0; | |
228 | } | |
229 | ||
ff6814d5 SS |
230 | /* Initialize a DMA channel. */ |
231 | static inline void init_dma(unsigned int dmanr) | |
1da177e4 LT |
232 | { |
233 | struct dma_chan *chan = get_dma_chan(dmanr); | |
234 | u32 mode; | |
ff6814d5 | 235 | |
1da177e4 LT |
236 | if (!chan) |
237 | return; | |
238 | ||
239 | disable_dma(dmanr); | |
240 | ||
ff6814d5 SS |
241 | /* Set device FIFO address */ |
242 | au_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR); | |
1da177e4 LT |
243 | |
244 | mode = chan->mode | (chan->dev_id << DMA_DID_BIT); | |
245 | if (chan->irq) | |
246 | mode |= DMA_IE; | |
247 | ||
248 | au_writel(~mode, chan->io + DMA_MODE_CLEAR); | |
70342287 | 249 | au_writel(mode, chan->io + DMA_MODE_SET); |
1da177e4 LT |
250 | } |
251 | ||
252 | /* | |
ff6814d5 | 253 | * Set mode for a specific DMA channel |
1da177e4 | 254 | */ |
ff6814d5 | 255 | static inline void set_dma_mode(unsigned int dmanr, unsigned int mode) |
1da177e4 LT |
256 | { |
257 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 258 | |
1da177e4 LT |
259 | if (!chan) |
260 | return; | |
261 | /* | |
262 | * set_dma_mode is only allowed to change endianess, direction, | |
263 | * transfer size, device FIFO width, and coherency settings. | |
264 | * Make sure anything else is masked off. | |
265 | */ | |
266 | mode &= (DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC); | |
267 | chan->mode &= ~(DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC); | |
268 | chan->mode |= mode; | |
269 | } | |
270 | ||
ff6814d5 | 271 | static inline unsigned int get_dma_mode(unsigned int dmanr) |
1da177e4 LT |
272 | { |
273 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 274 | |
1da177e4 LT |
275 | if (!chan) |
276 | return 0; | |
277 | return chan->mode; | |
278 | } | |
279 | ||
ff6814d5 | 280 | static inline int get_dma_active_buffer(unsigned int dmanr) |
1da177e4 LT |
281 | { |
282 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 283 | |
1da177e4 LT |
284 | if (!chan) |
285 | return -1; | |
286 | return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0; | |
287 | } | |
288 | ||
1da177e4 | 289 | /* |
ff6814d5 | 290 | * Set the device FIFO address for a specific DMA channel - only |
1da177e4 LT |
291 | * applicable to GPO4 and GPO5. All the other devices have fixed |
292 | * FIFO addresses. | |
293 | */ | |
ff6814d5 | 294 | static inline void set_dma_fifo_addr(unsigned int dmanr, unsigned int a) |
1da177e4 LT |
295 | { |
296 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 297 | |
1da177e4 LT |
298 | if (!chan) |
299 | return; | |
300 | ||
ff6814d5 | 301 | if (chan->mode & DMA_DS) /* second bank of device IDs */ |
1da177e4 LT |
302 | return; |
303 | ||
304 | if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05) | |
305 | return; | |
306 | ||
307 | au_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR); | |
308 | } | |
309 | ||
310 | /* | |
311 | * Clear the DMA buffer done bits in the mode register. | |
312 | */ | |
ff6814d5 | 313 | static inline void clear_dma_done0(unsigned int dmanr) |
1da177e4 LT |
314 | { |
315 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 316 | |
1da177e4 LT |
317 | if (!chan) |
318 | return; | |
319 | au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR); | |
320 | } | |
ff6814d5 SS |
321 | |
322 | static inline void clear_dma_done1(unsigned int dmanr) | |
1da177e4 LT |
323 | { |
324 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 325 | |
1da177e4 LT |
326 | if (!chan) |
327 | return; | |
328 | au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR); | |
329 | } | |
330 | ||
331 | /* | |
332 | * This does nothing - not applicable to Au1000 DMA. | |
333 | */ | |
ff6814d5 | 334 | static inline void set_dma_page(unsigned int dmanr, char pagenr) |
1da177e4 LT |
335 | { |
336 | } | |
337 | ||
338 | /* | |
339 | * Set Buffer 0 transfer address for specific DMA channel. | |
340 | */ | |
ff6814d5 | 341 | static inline void set_dma_addr0(unsigned int dmanr, unsigned int a) |
1da177e4 LT |
342 | { |
343 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 344 | |
1da177e4 LT |
345 | if (!chan) |
346 | return; | |
347 | au_writel(a, chan->io + DMA_BUFFER0_START); | |
348 | } | |
349 | ||
350 | /* | |
351 | * Set Buffer 1 transfer address for specific DMA channel. | |
352 | */ | |
ff6814d5 | 353 | static inline void set_dma_addr1(unsigned int dmanr, unsigned int a) |
1da177e4 LT |
354 | { |
355 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 356 | |
1da177e4 LT |
357 | if (!chan) |
358 | return; | |
359 | au_writel(a, chan->io + DMA_BUFFER1_START); | |
360 | } | |
361 | ||
362 | ||
363 | /* | |
364 | * Set Buffer 0 transfer size (max 64k) for a specific DMA channel. | |
365 | */ | |
ff6814d5 | 366 | static inline void set_dma_count0(unsigned int dmanr, unsigned int count) |
1da177e4 LT |
367 | { |
368 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 369 | |
1da177e4 LT |
370 | if (!chan) |
371 | return; | |
372 | count &= DMA_COUNT_MASK; | |
373 | au_writel(count, chan->io + DMA_BUFFER0_COUNT); | |
374 | } | |
375 | ||
376 | /* | |
377 | * Set Buffer 1 transfer size (max 64k) for a specific DMA channel. | |
378 | */ | |
ff6814d5 | 379 | static inline void set_dma_count1(unsigned int dmanr, unsigned int count) |
1da177e4 LT |
380 | { |
381 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 382 | |
1da177e4 LT |
383 | if (!chan) |
384 | return; | |
385 | count &= DMA_COUNT_MASK; | |
386 | au_writel(count, chan->io + DMA_BUFFER1_COUNT); | |
387 | } | |
388 | ||
389 | /* | |
390 | * Set both buffer transfer sizes (max 64k) for a specific DMA channel. | |
391 | */ | |
ff6814d5 | 392 | static inline void set_dma_count(unsigned int dmanr, unsigned int count) |
1da177e4 LT |
393 | { |
394 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 395 | |
1da177e4 LT |
396 | if (!chan) |
397 | return; | |
398 | count &= DMA_COUNT_MASK; | |
399 | au_writel(count, chan->io + DMA_BUFFER0_COUNT); | |
400 | au_writel(count, chan->io + DMA_BUFFER1_COUNT); | |
401 | } | |
402 | ||
403 | /* | |
404 | * Returns which buffer has its done bit set in the mode register. | |
405 | * Returns -1 if neither or both done bits set. | |
406 | */ | |
ff6814d5 | 407 | static inline unsigned int get_dma_buffer_done(unsigned int dmanr) |
1da177e4 LT |
408 | { |
409 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 410 | |
1da177e4 LT |
411 | if (!chan) |
412 | return 0; | |
ff6814d5 | 413 | return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1); |
1da177e4 LT |
414 | } |
415 | ||
416 | ||
417 | /* | |
418 | * Returns the DMA channel's Buffer Done IRQ number. | |
419 | */ | |
ff6814d5 | 420 | static inline int get_dma_done_irq(unsigned int dmanr) |
1da177e4 LT |
421 | { |
422 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 423 | |
1da177e4 LT |
424 | if (!chan) |
425 | return -1; | |
1da177e4 LT |
426 | return chan->irq; |
427 | } | |
428 | ||
429 | /* | |
430 | * Get DMA residue count. Returns the number of _bytes_ left to transfer. | |
431 | */ | |
ff6814d5 | 432 | static inline int get_dma_residue(unsigned int dmanr) |
1da177e4 LT |
433 | { |
434 | int curBufCntReg, count; | |
435 | struct dma_chan *chan = get_dma_chan(dmanr); | |
ff6814d5 | 436 | |
1da177e4 LT |
437 | if (!chan) |
438 | return 0; | |
439 | ||
440 | curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? | |
441 | DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT; | |
442 | ||
443 | count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK; | |
444 | ||
445 | if ((chan->mode & DMA_DW_MASK) == DMA_DW16) | |
446 | count <<= 1; | |
447 | else if ((chan->mode & DMA_DW_MASK) == DMA_DW32) | |
448 | count <<= 2; | |
449 | ||
450 | return count; | |
451 | } | |
452 | ||
453 | #endif /* __ASM_AU1000_DMA_H */ |