1/*
2 * dma.h - Blackfin DMA defines/structures/etc...
3 *
4 * Copyright 2004-2008 Analog Devices Inc.
5 * Licensed under the GPL-2 or later.
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 <linux/atomic.h>
14#include <asm/blackfin.h>
15#include <asm/page.h>
16#include <asm-generic/dma.h>
17#include <asm/bfin_dma.h>
18
19/*-------------------------
20 * config reg bits value
21 *-------------------------*/
22#define DATA_SIZE_8			0
23#define DATA_SIZE_16		1
24#define DATA_SIZE_32		2
25#ifdef CONFIG_BF60x
26#define DATA_SIZE_64		3
27#endif
28
29#define DMA_FLOW_STOP		0
30#define DMA_FLOW_AUTO		1
31#ifdef CONFIG_BF60x
32#define DMA_FLOW_LIST		4
33#define DMA_FLOW_ARRAY		5
34#define DMA_FLOW_LIST_DEMAND	6
35#define DMA_FLOW_ARRAY_DEMAND	7
36#else
37#define DMA_FLOW_ARRAY		4
38#define DMA_FLOW_SMALL		6
39#define DMA_FLOW_LARGE		7
40#endif
41
42#define DIMENSION_LINEAR	0
43#define DIMENSION_2D		1
44
45#define DIR_READ			0
46#define DIR_WRITE			1
47
48#define INTR_DISABLE		0
49#ifdef CONFIG_BF60x
50#define INTR_ON_PERI			1
51#endif
52#define INTR_ON_BUF			2
53#define INTR_ON_ROW			3
54
55#define DMA_NOSYNC_KEEP_DMA_BUF	0
56#define DMA_SYNC_RESTART		1
57
58#ifdef DMA_MMR_SIZE_32
59#define DMA_MMR_SIZE_TYPE long
60#define DMA_MMR_READ bfin_read32
61#define DMA_MMR_WRITE bfin_write32
62#else
63#define DMA_MMR_SIZE_TYPE short
64#define DMA_MMR_READ bfin_read16
65#define DMA_MMR_WRITE bfin_write16
66#endif
67
68struct dma_desc_array {
69	unsigned long start_addr;
70	unsigned DMA_MMR_SIZE_TYPE cfg;
71	unsigned DMA_MMR_SIZE_TYPE x_count;
72	DMA_MMR_SIZE_TYPE x_modify;
73} __attribute__((packed));
74
75struct dmasg {
76	void *next_desc_addr;
77	unsigned long start_addr;
78	unsigned DMA_MMR_SIZE_TYPE cfg;
79	unsigned DMA_MMR_SIZE_TYPE x_count;
80	DMA_MMR_SIZE_TYPE x_modify;
81	unsigned DMA_MMR_SIZE_TYPE y_count;
82	DMA_MMR_SIZE_TYPE y_modify;
83} __attribute__((packed));
84
85struct dma_register {
86	void *next_desc_ptr;	/* DMA Next Descriptor Pointer register */
87	unsigned long start_addr;	/* DMA Start address  register */
88#ifdef CONFIG_BF60x
89	unsigned long cfg;	/* DMA Configuration register */
90
91	unsigned long x_count;	/* DMA x_count register */
92
93	long x_modify;	/* DMA x_modify register */
94
95	unsigned long y_count;	/* DMA y_count register */
96
97	long y_modify;	/* DMA y_modify register */
98
99	unsigned long reserved;
100	unsigned long reserved2;
101
102	void *curr_desc_ptr;	/* DMA Current Descriptor Pointer
103					   register */
104	void *prev_desc_ptr;	/* DMA previous initial Descriptor Pointer
105					   register */
106	unsigned long curr_addr_ptr;	/* DMA Current Address Pointer
107						   register */
108	unsigned long irq_status;	/* DMA irq status register */
109
110	unsigned long curr_x_count;	/* DMA Current x-count register */
111
112	unsigned long curr_y_count;	/* DMA Current y-count register */
113
114	unsigned long reserved3;
115
116	unsigned long bw_limit_count;	/* DMA band width limit count register */
117	unsigned long curr_bw_limit_count;	/* DMA Current band width limit
118							count register */
119	unsigned long bw_monitor_count;	/* DMA band width limit count register */
120	unsigned long curr_bw_monitor_count;	/* DMA Current band width limit
121							count register */
122#else
123	unsigned short cfg;	/* DMA Configuration register */
124	unsigned short dummy1;	/* DMA Configuration register */
125
126	unsigned long reserved;
127
128	unsigned short x_count;	/* DMA x_count register */
129	unsigned short dummy2;
130
131	short x_modify;	/* DMA x_modify register */
132	unsigned short dummy3;
133
134	unsigned short y_count;	/* DMA y_count register */
135	unsigned short dummy4;
136
137	short y_modify;	/* DMA y_modify register */
138	unsigned short dummy5;
139
140	void *curr_desc_ptr;	/* DMA Current Descriptor Pointer
141					   register */
142	unsigned long curr_addr_ptr;	/* DMA Current Address Pointer
143						   register */
144	unsigned short irq_status;	/* DMA irq status register */
145	unsigned short dummy6;
146
147	unsigned short peripheral_map;	/* DMA peripheral map register */
148	unsigned short dummy7;
149
150	unsigned short curr_x_count;	/* DMA Current x-count register */
151	unsigned short dummy8;
152
153	unsigned long reserved2;
154
155	unsigned short curr_y_count;	/* DMA Current y-count register */
156	unsigned short dummy9;
157
158	unsigned long reserved3;
159#endif
160
161};
162
163struct dma_channel {
164	const char *device_id;
165	atomic_t chan_status;
166	volatile struct dma_register *regs;
167	struct dmasg *sg;		/* large mode descriptor */
168	unsigned int irq;
169	void *data;
170#ifdef CONFIG_PM
171	unsigned short saved_peripheral_map;
172#endif
173};
174
175#ifdef CONFIG_PM
176int blackfin_dma_suspend(void);
177void blackfin_dma_resume(void);
178#endif
179
180/*******************************************************************************
181*	DMA API's
182*******************************************************************************/
183extern struct dma_channel dma_ch[MAX_DMA_CHANNELS];
184extern struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS];
185extern int channel2irq(unsigned int channel);
186
187static inline void set_dma_start_addr(unsigned int channel, unsigned long addr)
188{
189	dma_ch[channel].regs->start_addr = addr;
190}
191static inline void set_dma_next_desc_addr(unsigned int channel, void *addr)
192{
193	dma_ch[channel].regs->next_desc_ptr = addr;
194}
195static inline void set_dma_curr_desc_addr(unsigned int channel, void *addr)
196{
197	dma_ch[channel].regs->curr_desc_ptr = addr;
198}
199static inline void set_dma_x_count(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE x_count)
200{
201	dma_ch[channel].regs->x_count = x_count;
202}
203static inline void set_dma_y_count(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE y_count)
204{
205	dma_ch[channel].regs->y_count = y_count;
206}
207static inline void set_dma_x_modify(unsigned int channel, DMA_MMR_SIZE_TYPE x_modify)
208{
209	dma_ch[channel].regs->x_modify = x_modify;
210}
211static inline void set_dma_y_modify(unsigned int channel, DMA_MMR_SIZE_TYPE y_modify)
212{
213	dma_ch[channel].regs->y_modify = y_modify;
214}
215static inline void set_dma_config(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE config)
216{
217	dma_ch[channel].regs->cfg = config;
218}
219static inline void set_dma_curr_addr(unsigned int channel, unsigned long addr)
220{
221	dma_ch[channel].regs->curr_addr_ptr = addr;
222}
223
224#ifdef CONFIG_BF60x
225static inline unsigned long
226set_bfin_dma_config2(char direction, char flow_mode, char intr_mode,
227		     char dma_mode, char mem_width, char syncmode, char peri_width)
228{
229	unsigned long config = 0;
230
231	switch (intr_mode) {
232	case INTR_ON_BUF:
233		if (dma_mode == DIMENSION_2D)
234			config = DI_EN_Y;
235		else
236			config = DI_EN_X;
237		break;
238	case INTR_ON_ROW:
239		config = DI_EN_X;
240		break;
241	case INTR_ON_PERI:
242		config = DI_EN_P;
243		break;
244	};
245
246	return config | (direction << 1) | (mem_width << 8) | (dma_mode << 26) |
247		(flow_mode << 12) | (syncmode << 2) | (peri_width << 4);
248}
249#endif
250
251static inline unsigned DMA_MMR_SIZE_TYPE
252set_bfin_dma_config(char direction, char flow_mode,
253		    char intr_mode, char dma_mode, char mem_width, char syncmode)
254{
255#ifdef CONFIG_BF60x
256	return set_bfin_dma_config2(direction, flow_mode, intr_mode, dma_mode,
257		mem_width, syncmode, mem_width);
258#else
259	return (direction << 1) | (mem_width << 2) | (dma_mode << 4) |
260		(intr_mode << 6) | (flow_mode << 12) | (syncmode << 5);
261#endif
262}
263
264static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_irqstat(unsigned int channel)
265{
266	return dma_ch[channel].regs->irq_status;
267}
268static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_xcount(unsigned int channel)
269{
270	return dma_ch[channel].regs->curr_x_count;
271}
272static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_ycount(unsigned int channel)
273{
274	return dma_ch[channel].regs->curr_y_count;
275}
276static inline void *get_dma_next_desc_ptr(unsigned int channel)
277{
278	return dma_ch[channel].regs->next_desc_ptr;
279}
280static inline void *get_dma_curr_desc_ptr(unsigned int channel)
281{
282	return dma_ch[channel].regs->curr_desc_ptr;
283}
284static inline unsigned DMA_MMR_SIZE_TYPE get_dma_config(unsigned int channel)
285{
286	return dma_ch[channel].regs->cfg;
287}
288static inline unsigned long get_dma_curr_addr(unsigned int channel)
289{
290	return dma_ch[channel].regs->curr_addr_ptr;
291}
292
293static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize)
294{
295	/* Make sure the internal data buffers in the core are drained
296	 * so that the DMA descriptors are completely written when the
297	 * DMA engine goes to fetch them below.
298	 */
299	SSYNC();
300
301	dma_ch[channel].regs->next_desc_ptr = sg;
302	dma_ch[channel].regs->cfg =
303		(dma_ch[channel].regs->cfg & ~NDSIZE) |
304		((ndsize << NDSIZE_OFFSET) & NDSIZE);
305}
306
307static inline int dma_channel_active(unsigned int channel)
308{
309	return atomic_read(&dma_ch[channel].chan_status);
310}
311
312static inline void disable_dma(unsigned int channel)
313{
314	dma_ch[channel].regs->cfg &= ~DMAEN;
315	SSYNC();
316}
317static inline void enable_dma(unsigned int channel)
318{
319	dma_ch[channel].regs->curr_x_count = 0;
320	dma_ch[channel].regs->curr_y_count = 0;
321	dma_ch[channel].regs->cfg |= DMAEN;
322}
323int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data);
324
325static inline void dma_disable_irq(unsigned int channel)
326{
327	disable_irq(dma_ch[channel].irq);
328}
329static inline void dma_disable_irq_nosync(unsigned int channel)
330{
331	disable_irq_nosync(dma_ch[channel].irq);
332}
333static inline void dma_enable_irq(unsigned int channel)
334{
335	enable_irq(dma_ch[channel].irq);
336}
337static inline void clear_dma_irqstat(unsigned int channel)
338{
339	dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR | DMA_PIRQ;
340}
341
342void *dma_memcpy(void *dest, const void *src, size_t count);
343void *dma_memcpy_nocache(void *dest, const void *src, size_t count);
344void *safe_dma_memcpy(void *dest, const void *src, size_t count);
345void blackfin_dma_early_init(void);
346void early_dma_memcpy(void *dest, const void *src, size_t count);
347void early_dma_memcpy_done(void);
348
349#endif
350