1
2
3
4
5
6
7
8#ifndef _BLACKFIN_DMA_H_
9#define _BLACKFIN_DMA_H_
10
11#include <linux/interrupt.h>
12#include <mach/dma.h>
13#include <asm/blackfin.h>
14#include <asm/page.h>
15
16#define MAX_DMA_ADDRESS PAGE_OFFSET
17
18
19
20
21
22enum dma_chan_status {
23 DMA_CHANNEL_FREE,
24 DMA_CHANNEL_REQUESTED,
25 DMA_CHANNEL_ENABLED,
26};
27
28
29
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
51#define DMA_NOSYNC_KEEP_DMA_BUF 0
52#define DMA_SYNC_RESTART 1
53
54struct dmasg {
55 void *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 void *next_desc_ptr;
66 unsigned long start_addr;
67
68 unsigned short cfg;
69 unsigned short dummy1;
70
71 unsigned long reserved;
72
73 unsigned short x_count;
74 unsigned short dummy2;
75
76 short x_modify;
77 unsigned short dummy3;
78
79 unsigned short y_count;
80 unsigned short dummy4;
81
82 short y_modify;
83 unsigned short dummy5;
84
85 void *curr_desc_ptr;
86
87 unsigned long curr_addr_ptr;
88
89 unsigned short irq_status;
90 unsigned short dummy6;
91
92 unsigned short peripheral_map;
93 unsigned short dummy7;
94
95 unsigned short curr_x_count;
96 unsigned short dummy8;
97
98 unsigned long reserved2;
99
100 unsigned short curr_y_count;
101 unsigned short dummy9;
102
103 unsigned long reserved3;
104
105};
106
107struct mutex;
108struct dma_channel {
109 struct mutex dmalock;
110 const char *device_id;
111 enum dma_chan_status chan_status;
112 volatile struct dma_register *regs;
113 struct dmasg *sg;
114 unsigned int irq;
115 void *data;
116#ifdef CONFIG_PM
117 unsigned short saved_peripheral_map;
118#endif
119};
120
121#ifdef CONFIG_PM
122int blackfin_dma_suspend(void);
123void blackfin_dma_resume(void);
124#endif
125
126
127
128
129extern struct dma_channel dma_ch[MAX_DMA_CHANNELS];
130extern struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS];
131extern int channel2irq(unsigned int channel);
132
133static inline void set_dma_start_addr(unsigned int channel, unsigned long addr)
134{
135 dma_ch[channel].regs->start_addr = addr;
136}
137static inline void set_dma_next_desc_addr(unsigned int channel, void *addr)
138{
139 dma_ch[channel].regs->next_desc_ptr = addr;
140}
141static inline void set_dma_curr_desc_addr(unsigned int channel, void *addr)
142{
143 dma_ch[channel].regs->curr_desc_ptr = addr;
144}
145static inline void set_dma_x_count(unsigned int channel, unsigned short x_count)
146{
147 dma_ch[channel].regs->x_count = x_count;
148}
149static inline void set_dma_y_count(unsigned int channel, unsigned short y_count)
150{
151 dma_ch[channel].regs->y_count = y_count;
152}
153static inline void set_dma_x_modify(unsigned int channel, short x_modify)
154{
155 dma_ch[channel].regs->x_modify = x_modify;
156}
157static inline void set_dma_y_modify(unsigned int channel, short y_modify)
158{
159 dma_ch[channel].regs->y_modify = y_modify;
160}
161static inline void set_dma_config(unsigned int channel, unsigned short config)
162{
163 dma_ch[channel].regs->cfg = config;
164}
165static inline void set_dma_curr_addr(unsigned int channel, unsigned long addr)
166{
167 dma_ch[channel].regs->curr_addr_ptr = addr;
168}
169
170static inline unsigned short
171set_bfin_dma_config(char direction, char flow_mode,
172 char intr_mode, char dma_mode, char width, char syncmode)
173{
174 return (direction << 1) | (width << 2) | (dma_mode << 4) |
175 (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5);
176}
177
178static inline unsigned short get_dma_curr_irqstat(unsigned int channel)
179{
180 return dma_ch[channel].regs->irq_status;
181}
182static inline unsigned short get_dma_curr_xcount(unsigned int channel)
183{
184 return dma_ch[channel].regs->curr_x_count;
185}
186static inline unsigned short get_dma_curr_ycount(unsigned int channel)
187{
188 return dma_ch[channel].regs->curr_y_count;
189}
190static inline void *get_dma_next_desc_ptr(unsigned int channel)
191{
192 return dma_ch[channel].regs->next_desc_ptr;
193}
194static inline void *get_dma_curr_desc_ptr(unsigned int channel)
195{
196 return dma_ch[channel].regs->curr_desc_ptr;
197}
198static inline unsigned short get_dma_config(unsigned int channel)
199{
200 return dma_ch[channel].regs->cfg;
201}
202static inline unsigned long get_dma_curr_addr(unsigned int channel)
203{
204 return dma_ch[channel].regs->curr_addr_ptr;
205}
206
207static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize)
208{
209
210
211
212
213 SSYNC();
214
215 dma_ch[channel].regs->next_desc_ptr = sg;
216 dma_ch[channel].regs->cfg =
217 (dma_ch[channel].regs->cfg & ~(0xf << 8)) |
218 ((ndsize & 0xf) << 8);
219}
220
221static inline int dma_channel_active(unsigned int channel)
222{
223 if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE)
224 return 0;
225 else
226 return 1;
227}
228
229static inline void disable_dma(unsigned int channel)
230{
231 dma_ch[channel].regs->cfg &= ~DMAEN;
232 SSYNC();
233 dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
234}
235static inline void enable_dma(unsigned int channel)
236{
237 dma_ch[channel].regs->curr_x_count = 0;
238 dma_ch[channel].regs->curr_y_count = 0;
239 dma_ch[channel].regs->cfg |= DMAEN;
240 dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
241}
242void free_dma(unsigned int channel);
243int request_dma(unsigned int channel, const char *device_id);
244int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data);
245
246static inline void dma_disable_irq(unsigned int channel)
247{
248 disable_irq(dma_ch[channel].irq);
249}
250static inline void dma_enable_irq(unsigned int channel)
251{
252 enable_irq(dma_ch[channel].irq);
253}
254static inline void clear_dma_irqstat(unsigned int channel)
255{
256 dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR;
257}
258
259void *dma_memcpy(void *dest, const void *src, size_t count);
260void *safe_dma_memcpy(void *dest, const void *src, size_t count);
261void blackfin_dma_early_init(void);
262void early_dma_memcpy(void *dest, const void *src, size_t count);
263void early_dma_memcpy_done(void);
264
265#endif
266