blob: 690c25f5f9928824638a8d7561350cdb44ea5887 [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
Mike Frysingerb03f2032009-01-07 23:14:38 +08002 * dma.h - Blackfin DMA defines/structures/etc...
Bryan Wu1394f032007-05-06 14:50:22 -07003 *
Mike Frysingerb03f2032009-01-07 23:14:38 +08004 * Copyright 2004-2008 Analog Devices Inc.
5 * Licensed under the GPL-2 or later.
Bryan Wu1394f032007-05-06 14:50:22 -07006 */
7
8#ifndef _BLACKFIN_DMA_H_
9#define _BLACKFIN_DMA_H_
10
Bryan Wu1394f032007-05-06 14:50:22 -070011#include <linux/interrupt.h>
Mike Frysinger4c1ed6a2009-01-07 23:14:38 +080012#include <mach/dma.h>
Bryan Wu1394f032007-05-06 14:50:22 -070013#include <asm/blackfin.h>
Mike Frysinger4c1ed6a2009-01-07 23:14:38 +080014#include <asm/page.h>
Bryan Wu1394f032007-05-06 14:50:22 -070015
16#define MAX_DMA_ADDRESS PAGE_OFFSET
17
18/*****************************************************************************
19* Generic DMA Declarations
20*
21****************************************************************************/
22enum dma_chan_status {
23 DMA_CHANNEL_FREE,
24 DMA_CHANNEL_REQUESTED,
25 DMA_CHANNEL_ENABLED,
26};
27
28/*-------------------------
29 * config reg bits value
30 *-------------------------*/
31#define DATA_SIZE_8 0
32#define DATA_SIZE_16 1
33#define DATA_SIZE_32 2
34
35#define DMA_FLOW_STOP 0
36#define DMA_FLOW_AUTO 1
37#define DMA_FLOW_ARRAY 4
38#define DMA_FLOW_SMALL 6
39#define DMA_FLOW_LARGE 7
40
41#define DIMENSION_LINEAR 0
42#define DIMENSION_2D 1
43
44#define DIR_READ 0
45#define DIR_WRITE 1
46
47#define INTR_DISABLE 0
48#define INTR_ON_BUF 2
49#define INTR_ON_ROW 3
50
Michael Hennerich2047e402008-01-22 15:29:18 +080051#define DMA_NOSYNC_KEEP_DMA_BUF 0
52#define DMA_SYNC_RESTART 1
53
Bryan Wu1394f032007-05-06 14:50:22 -070054struct dmasg {
55 unsigned long next_desc_addr;
56 unsigned long start_addr;
57 unsigned short cfg;
58 unsigned short x_count;
59 short x_modify;
60 unsigned short y_count;
61 short y_modify;
62} __attribute__((packed));
63
64struct dma_register {
65 unsigned long next_desc_ptr; /* DMA Next Descriptor Pointer register */
66 unsigned long start_addr; /* DMA Start address register */
67
68 unsigned short cfg; /* DMA Configuration register */
69 unsigned short dummy1; /* DMA Configuration register */
70
71 unsigned long reserved;
72
73 unsigned short x_count; /* DMA x_count register */
74 unsigned short dummy2;
75
76 short x_modify; /* DMA x_modify register */
77 unsigned short dummy3;
78
79 unsigned short y_count; /* DMA y_count register */
80 unsigned short dummy4;
81
82 short y_modify; /* DMA y_modify register */
83 unsigned short dummy5;
84
85 unsigned long curr_desc_ptr; /* DMA Current Descriptor Pointer
86 register */
Bryan Wu452af712007-10-22 00:02:14 +080087 unsigned long curr_addr_ptr; /* DMA Current Address Pointer
Bryan Wu1394f032007-05-06 14:50:22 -070088 register */
89 unsigned short irq_status; /* DMA irq status register */
90 unsigned short dummy6;
91
92 unsigned short peripheral_map; /* DMA peripheral map register */
93 unsigned short dummy7;
94
95 unsigned short curr_x_count; /* DMA Current x-count register */
96 unsigned short dummy8;
97
98 unsigned long reserved2;
99
100 unsigned short curr_y_count; /* DMA Current y-count register */
101 unsigned short dummy9;
102
103 unsigned long reserved3;
104
105};
106
Mike Frysinger4c1ed6a2009-01-07 23:14:38 +0800107struct mutex;
Bryan Wu1394f032007-05-06 14:50:22 -0700108struct dma_channel {
109 struct mutex dmalock;
Michael McTernan99532fd2009-01-07 23:14:38 +0800110 const char *device_id;
Bryan Wu1394f032007-05-06 14:50:22 -0700111 enum dma_chan_status chan_status;
112 struct dma_register *regs;
113 struct dmasg *sg; /* large mode descriptor */
114 unsigned int ctrl_num; /* controller number */
Michael Hennericha2ba8b12008-10-28 18:19:29 +0800115 unsigned int irq;
Bryan Wu1394f032007-05-06 14:50:22 -0700116 void *data;
117 unsigned int dma_enable_flag;
118 unsigned int loopback_flag;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800119#ifdef CONFIG_PM
120 unsigned short saved_peripheral_map;
121#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700122};
123
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800124#ifdef CONFIG_PM
125int blackfin_dma_suspend(void);
126void blackfin_dma_resume(void);
127#endif
128
Bryan Wu1394f032007-05-06 14:50:22 -0700129/*******************************************************************************
130* DMA API's
131*******************************************************************************/
Mike Frysinger9c417a42009-01-07 23:14:39 +0800132extern struct dma_channel dma_ch[MAX_DMA_CHANNELS];
133extern struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS];
134extern int channel2irq(unsigned int channel);
Bryan Wu1394f032007-05-06 14:50:22 -0700135
Mike Frysinger9c417a42009-01-07 23:14:39 +0800136static inline void set_dma_start_addr(unsigned int channel, unsigned long addr)
137{
138 dma_ch[channel].regs->start_addr = addr;
139}
140static inline void set_dma_next_desc_addr(unsigned int channel, unsigned long addr)
141{
142 dma_ch[channel].regs->next_desc_ptr = addr;
143}
144static inline void set_dma_curr_desc_addr(unsigned int channel, unsigned long addr)
145{
146 dma_ch[channel].regs->curr_desc_ptr = addr;
147}
148static inline void set_dma_x_count(unsigned int channel, unsigned short x_count)
149{
150 dma_ch[channel].regs->x_count = x_count;
151}
152static inline void set_dma_y_count(unsigned int channel, unsigned short y_count)
153{
154 dma_ch[channel].regs->y_count = y_count;
155}
156static inline void set_dma_x_modify(unsigned int channel, short x_modify)
157{
158 dma_ch[channel].regs->x_modify = x_modify;
159}
160static inline void set_dma_y_modify(unsigned int channel, short y_modify)
161{
162 dma_ch[channel].regs->y_modify = y_modify;
163}
164static inline void set_dma_config(unsigned int channel, unsigned short config)
165{
166 dma_ch[channel].regs->cfg = config;
167}
168static inline void set_dma_curr_addr(unsigned int channel, unsigned long addr)
169{
170 dma_ch[channel].regs->curr_addr_ptr = addr;
171}
Bryan Wu1394f032007-05-06 14:50:22 -0700172
Mike Frysinger9c417a42009-01-07 23:14:39 +0800173static inline unsigned short
174set_bfin_dma_config(char direction, char flow_mode,
175 char intr_mode, char dma_mode, char width, char syncmode)
176{
177 return (direction << 1) | (width << 2) | (dma_mode << 4) |
178 (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5);
179}
Bryan Wu1394f032007-05-06 14:50:22 -0700180
Mike Frysinger9c417a42009-01-07 23:14:39 +0800181static inline unsigned short get_dma_curr_irqstat(unsigned int channel)
182{
183 return dma_ch[channel].regs->irq_status;
184}
185static inline unsigned short get_dma_curr_xcount(unsigned int channel)
186{
187 return dma_ch[channel].regs->curr_x_count;
188}
189static inline unsigned short get_dma_curr_ycount(unsigned int channel)
190{
191 return dma_ch[channel].regs->curr_y_count;
192}
193static inline unsigned long get_dma_next_desc_ptr(unsigned int channel)
194{
195 return dma_ch[channel].regs->next_desc_ptr;
196}
197static inline unsigned long get_dma_curr_desc_ptr(unsigned int channel)
198{
199 return dma_ch[channel].regs->curr_desc_ptr;
200}
201static inline unsigned long get_dma_curr_addr(unsigned int channel)
202{
203 return dma_ch[channel].regs->curr_addr_ptr;
204}
Bryan Wu1394f032007-05-06 14:50:22 -0700205
Mike Frysinger9c417a42009-01-07 23:14:39 +0800206static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize)
207{
208 dma_ch[channel].regs->cfg |= ((ndsize & 0x0F) << 8);
209 dma_ch[channel].regs->next_desc_ptr = (unsigned long)sg;
210}
211
212static inline int dma_channel_active(unsigned int channel)
213{
214 if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE)
215 return 0;
216 else
217 return 1;
218}
219
220static inline void disable_dma(unsigned int channel)
221{
222 dma_ch[channel].regs->cfg &= ~DMAEN;
223 SSYNC();
224 dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
225}
226static inline void enable_dma(unsigned int channel)
227{
228 dma_ch[channel].regs->curr_x_count = 0;
229 dma_ch[channel].regs->curr_y_count = 0;
230 dma_ch[channel].regs->cfg |= DMAEN;
231 dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
232}
Bryan Wu1394f032007-05-06 14:50:22 -0700233void free_dma(unsigned int channel);
Michael McTernan99532fd2009-01-07 23:14:38 +0800234int request_dma(unsigned int channel, const char *device_id);
Mike Frysinger9c417a42009-01-07 23:14:39 +0800235int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data);
236
237static inline void dma_disable_irq(unsigned int channel)
238{
239 disable_irq(dma_ch[channel].irq);
240}
241static inline void dma_enable_irq(unsigned int channel)
242{
243 enable_irq(dma_ch[channel].irq);
244}
245static inline void clear_dma_irqstat(unsigned int channel)
246{
247 dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR;
248}
249
Bryan Wu1394f032007-05-06 14:50:22 -0700250void *dma_memcpy(void *dest, const void *src, size_t count);
251void *safe_dma_memcpy(void *dest, const void *src, size_t count);
Mike Frysingerdd3dd382009-01-07 23:14:39 +0800252void blackfin_dma_early_init(void);
Bryan Wu1394f032007-05-06 14:50:22 -0700253
Bryan Wu1394f032007-05-06 14:50:22 -0700254#endif