]>
Commit | Line | Data |
---|---|---|
1394f032 | 1 | /* |
b03f2039 | 2 | * dma.h - Blackfin DMA defines/structures/etc... |
1394f032 | 3 | * |
b03f2039 MF |
4 | * Copyright 2004-2008 Analog Devices Inc. |
5 | * Licensed under the GPL-2 or later. | |
1394f032 BW |
6 | */ |
7 | ||
8 | #ifndef _BLACKFIN_DMA_H_ | |
9 | #define _BLACKFIN_DMA_H_ | |
10 | ||
1394f032 | 11 | #include <linux/interrupt.h> |
4c1ed6a5 | 12 | #include <mach/dma.h> |
60063497 | 13 | #include <linux/atomic.h> |
1394f032 | 14 | #include <asm/blackfin.h> |
4c1ed6a5 | 15 | #include <asm/page.h> |
dd3b0e3e | 16 | #include <asm-generic/dma.h> |
6c8e75a0 | 17 | #include <asm/bfin_dma.h> |
1394f032 BW |
18 | |
19 | /*------------------------- | |
20 | * config reg bits value | |
21 | *-------------------------*/ | |
00d24604 MF |
22 | #define DATA_SIZE_8 0 |
23 | #define DATA_SIZE_16 1 | |
24 | #define DATA_SIZE_32 2 | |
1394f032 | 25 | |
00d24604 MF |
26 | #define DMA_FLOW_STOP 0 |
27 | #define DMA_FLOW_AUTO 1 | |
28 | #define DMA_FLOW_ARRAY 4 | |
29 | #define DMA_FLOW_SMALL 6 | |
30 | #define DMA_FLOW_LARGE 7 | |
1394f032 | 31 | |
00d24604 MF |
32 | #define DIMENSION_LINEAR 0 |
33 | #define DIMENSION_2D 1 | |
1394f032 | 34 | |
00d24604 MF |
35 | #define DIR_READ 0 |
36 | #define DIR_WRITE 1 | |
1394f032 | 37 | |
00d24604 MF |
38 | #define INTR_DISABLE 0 |
39 | #define INTR_ON_BUF 2 | |
40 | #define INTR_ON_ROW 3 | |
1394f032 | 41 | |
2047e40d | 42 | #define DMA_NOSYNC_KEEP_DMA_BUF 0 |
00d24604 | 43 | #define DMA_SYNC_RESTART 1 |
2047e40d | 44 | |
1394f032 | 45 | struct dmasg { |
6ab729d8 | 46 | void *next_desc_addr; |
1394f032 BW |
47 | unsigned long start_addr; |
48 | unsigned short cfg; | |
49 | unsigned short x_count; | |
50 | short x_modify; | |
51 | unsigned short y_count; | |
52 | short y_modify; | |
53 | } __attribute__((packed)); | |
54 | ||
55 | struct dma_register { | |
6ab729d8 | 56 | void *next_desc_ptr; /* DMA Next Descriptor Pointer register */ |
1394f032 BW |
57 | unsigned long start_addr; /* DMA Start address register */ |
58 | ||
59 | unsigned short cfg; /* DMA Configuration register */ | |
60 | unsigned short dummy1; /* DMA Configuration register */ | |
61 | ||
62 | unsigned long reserved; | |
63 | ||
64 | unsigned short x_count; /* DMA x_count register */ | |
65 | unsigned short dummy2; | |
66 | ||
67 | short x_modify; /* DMA x_modify register */ | |
68 | unsigned short dummy3; | |
69 | ||
70 | unsigned short y_count; /* DMA y_count register */ | |
71 | unsigned short dummy4; | |
72 | ||
73 | short y_modify; /* DMA y_modify register */ | |
74 | unsigned short dummy5; | |
75 | ||
6ab729d8 | 76 | void *curr_desc_ptr; /* DMA Current Descriptor Pointer |
1394f032 | 77 | register */ |
452af71f | 78 | unsigned long curr_addr_ptr; /* DMA Current Address Pointer |
1394f032 BW |
79 | register */ |
80 | unsigned short irq_status; /* DMA irq status register */ | |
81 | unsigned short dummy6; | |
82 | ||
83 | unsigned short peripheral_map; /* DMA peripheral map register */ | |
84 | unsigned short dummy7; | |
85 | ||
86 | unsigned short curr_x_count; /* DMA Current x-count register */ | |
87 | unsigned short dummy8; | |
88 | ||
89 | unsigned long reserved2; | |
90 | ||
91 | unsigned short curr_y_count; /* DMA Current y-count register */ | |
92 | unsigned short dummy9; | |
93 | ||
94 | unsigned long reserved3; | |
95 | ||
96 | }; | |
97 | ||
1394f032 | 98 | struct dma_channel { |
99532fd2 | 99 | const char *device_id; |
d2e015d6 | 100 | atomic_t chan_status; |
4ce18736 | 101 | volatile struct dma_register *regs; |
1394f032 | 102 | struct dmasg *sg; /* large mode descriptor */ |
a2ba8b19 | 103 | unsigned int irq; |
1394f032 | 104 | void *data; |
1efc80b5 MH |
105 | #ifdef CONFIG_PM |
106 | unsigned short saved_peripheral_map; | |
107 | #endif | |
1394f032 BW |
108 | }; |
109 | ||
1efc80b5 MH |
110 | #ifdef CONFIG_PM |
111 | int blackfin_dma_suspend(void); | |
112 | void blackfin_dma_resume(void); | |
113 | #endif | |
114 | ||
1394f032 BW |
115 | /******************************************************************************* |
116 | * DMA API's | |
117 | *******************************************************************************/ | |
9c417a43 | 118 | extern struct dma_channel dma_ch[MAX_DMA_CHANNELS]; |
5e3bcf30 | 119 | extern struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS]; |
9c417a43 MF |
120 | extern int channel2irq(unsigned int channel); |
121 | ||
122 | static inline void set_dma_start_addr(unsigned int channel, unsigned long addr) | |
123 | { | |
124 | dma_ch[channel].regs->start_addr = addr; | |
125 | } | |
6ab729d8 | 126 | static inline void set_dma_next_desc_addr(unsigned int channel, void *addr) |
9c417a43 MF |
127 | { |
128 | dma_ch[channel].regs->next_desc_ptr = addr; | |
129 | } | |
6ab729d8 | 130 | static inline void set_dma_curr_desc_addr(unsigned int channel, void *addr) |
9c417a43 MF |
131 | { |
132 | dma_ch[channel].regs->curr_desc_ptr = addr; | |
133 | } | |
134 | static inline void set_dma_x_count(unsigned int channel, unsigned short x_count) | |
135 | { | |
136 | dma_ch[channel].regs->x_count = x_count; | |
137 | } | |
138 | static inline void set_dma_y_count(unsigned int channel, unsigned short y_count) | |
139 | { | |
140 | dma_ch[channel].regs->y_count = y_count; | |
141 | } | |
142 | static inline void set_dma_x_modify(unsigned int channel, short x_modify) | |
143 | { | |
144 | dma_ch[channel].regs->x_modify = x_modify; | |
145 | } | |
146 | static inline void set_dma_y_modify(unsigned int channel, short y_modify) | |
147 | { | |
148 | dma_ch[channel].regs->y_modify = y_modify; | |
149 | } | |
150 | static inline void set_dma_config(unsigned int channel, unsigned short config) | |
151 | { | |
152 | dma_ch[channel].regs->cfg = config; | |
153 | } | |
154 | static inline void set_dma_curr_addr(unsigned int channel, unsigned long addr) | |
155 | { | |
156 | dma_ch[channel].regs->curr_addr_ptr = addr; | |
157 | } | |
158 | ||
159 | static inline unsigned short | |
160 | set_bfin_dma_config(char direction, char flow_mode, | |
161 | char intr_mode, char dma_mode, char width, char syncmode) | |
162 | { | |
163 | return (direction << 1) | (width << 2) | (dma_mode << 4) | | |
164 | (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5); | |
165 | } | |
166 | ||
167 | static inline unsigned short get_dma_curr_irqstat(unsigned int channel) | |
168 | { | |
169 | return dma_ch[channel].regs->irq_status; | |
170 | } | |
171 | static inline unsigned short get_dma_curr_xcount(unsigned int channel) | |
172 | { | |
173 | return dma_ch[channel].regs->curr_x_count; | |
174 | } | |
175 | static inline unsigned short get_dma_curr_ycount(unsigned int channel) | |
176 | { | |
177 | return dma_ch[channel].regs->curr_y_count; | |
178 | } | |
6ab729d8 | 179 | static inline void *get_dma_next_desc_ptr(unsigned int channel) |
9c417a43 MF |
180 | { |
181 | return dma_ch[channel].regs->next_desc_ptr; | |
182 | } | |
6ab729d8 | 183 | static inline void *get_dma_curr_desc_ptr(unsigned int channel) |
9c417a43 MF |
184 | { |
185 | return dma_ch[channel].regs->curr_desc_ptr; | |
186 | } | |
71f5ca35 MF |
187 | static inline unsigned short get_dma_config(unsigned int channel) |
188 | { | |
189 | return dma_ch[channel].regs->cfg; | |
190 | } | |
9c417a43 MF |
191 | static inline unsigned long get_dma_curr_addr(unsigned int channel) |
192 | { | |
193 | return dma_ch[channel].regs->curr_addr_ptr; | |
194 | } | |
195 | ||
196 | static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize) | |
197 | { | |
ea8538a0 SZ |
198 | /* Make sure the internal data buffers in the core are drained |
199 | * so that the DMA descriptors are completely written when the | |
200 | * DMA engine goes to fetch them below. | |
201 | */ | |
202 | SSYNC(); | |
203 | ||
204 | dma_ch[channel].regs->next_desc_ptr = sg; | |
d41e8009 MF |
205 | dma_ch[channel].regs->cfg = |
206 | (dma_ch[channel].regs->cfg & ~(0xf << 8)) | | |
207 | ((ndsize & 0xf) << 8); | |
9c417a43 MF |
208 | } |
209 | ||
210 | static inline int dma_channel_active(unsigned int channel) | |
211 | { | |
d2e015d6 | 212 | return atomic_read(&dma_ch[channel].chan_status); |
9c417a43 MF |
213 | } |
214 | ||
215 | static inline void disable_dma(unsigned int channel) | |
216 | { | |
217 | dma_ch[channel].regs->cfg &= ~DMAEN; | |
218 | SSYNC(); | |
9c417a43 MF |
219 | } |
220 | static inline void enable_dma(unsigned int channel) | |
221 | { | |
222 | dma_ch[channel].regs->curr_x_count = 0; | |
223 | dma_ch[channel].regs->curr_y_count = 0; | |
224 | dma_ch[channel].regs->cfg |= DMAEN; | |
9c417a43 | 225 | } |
9c417a43 MF |
226 | int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data); |
227 | ||
228 | static inline void dma_disable_irq(unsigned int channel) | |
229 | { | |
230 | disable_irq(dma_ch[channel].irq); | |
231 | } | |
4ab069e5 BS |
232 | static inline void dma_disable_irq_nosync(unsigned int channel) |
233 | { | |
234 | disable_irq_nosync(dma_ch[channel].irq); | |
235 | } | |
9c417a43 MF |
236 | static inline void dma_enable_irq(unsigned int channel) |
237 | { | |
238 | enable_irq(dma_ch[channel].irq); | |
239 | } | |
240 | static inline void clear_dma_irqstat(unsigned int channel) | |
241 | { | |
242 | dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR; | |
243 | } | |
244 | ||
1394f032 | 245 | void *dma_memcpy(void *dest, const void *src, size_t count); |
d1401e1d | 246 | void *dma_memcpy_nocache(void *dest, const void *src, size_t count); |
1394f032 | 247 | void *safe_dma_memcpy(void *dest, const void *src, size_t count); |
dd3dd384 | 248 | void blackfin_dma_early_init(void); |
fecbd736 RG |
249 | void early_dma_memcpy(void *dest, const void *src, size_t count); |
250 | void early_dma_memcpy_done(void); | |
1394f032 BW |
251 | |
252 | #endif |