blob: e3c0dfa73d1bd396449acdeece2441544c35cc9f [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>
Mike Frysingerd2e015d2009-10-09 22:18:12 +000013#include <asm/atomic.h>
Bryan Wu1394f032007-05-06 14:50:22 -070014#include <asm/blackfin.h>
Mike Frysinger4c1ed6a2009-01-07 23:14:38 +080015#include <asm/page.h>
Bryan Wu1394f032007-05-06 14:50:22 -070016
17#define MAX_DMA_ADDRESS PAGE_OFFSET
18
19/*****************************************************************************
20* Generic DMA Declarations
21*
22****************************************************************************/
Bryan Wu1394f032007-05-06 14:50:22 -070023
24/*-------------------------
25 * config reg bits value
26 *-------------------------*/
27#define DATA_SIZE_8 0
28#define DATA_SIZE_16 1
29#define DATA_SIZE_32 2
30
31#define DMA_FLOW_STOP 0
32#define DMA_FLOW_AUTO 1
33#define DMA_FLOW_ARRAY 4
34#define DMA_FLOW_SMALL 6
35#define DMA_FLOW_LARGE 7
36
37#define DIMENSION_LINEAR 0
38#define DIMENSION_2D 1
39
40#define DIR_READ 0
41#define DIR_WRITE 1
42
43#define INTR_DISABLE 0
44#define INTR_ON_BUF 2
45#define INTR_ON_ROW 3
46
Michael Hennerich2047e402008-01-22 15:29:18 +080047#define DMA_NOSYNC_KEEP_DMA_BUF 0
48#define DMA_SYNC_RESTART 1
49
Bryan Wu1394f032007-05-06 14:50:22 -070050struct dmasg {
Mike Frysinger6ab729d2009-01-07 23:14:38 +080051 void *next_desc_addr;
Bryan Wu1394f032007-05-06 14:50:22 -070052 unsigned long start_addr;
53 unsigned short cfg;
54 unsigned short x_count;
55 short x_modify;
56 unsigned short y_count;
57 short y_modify;
58} __attribute__((packed));
59
60struct dma_register {
Mike Frysinger6ab729d2009-01-07 23:14:38 +080061 void *next_desc_ptr; /* DMA Next Descriptor Pointer register */
Bryan Wu1394f032007-05-06 14:50:22 -070062 unsigned long start_addr; /* DMA Start address register */
63
64 unsigned short cfg; /* DMA Configuration register */
65 unsigned short dummy1; /* DMA Configuration register */
66
67 unsigned long reserved;
68
69 unsigned short x_count; /* DMA x_count register */
70 unsigned short dummy2;
71
72 short x_modify; /* DMA x_modify register */
73 unsigned short dummy3;
74
75 unsigned short y_count; /* DMA y_count register */
76 unsigned short dummy4;
77
78 short y_modify; /* DMA y_modify register */
79 unsigned short dummy5;
80
Mike Frysinger6ab729d2009-01-07 23:14:38 +080081 void *curr_desc_ptr; /* DMA Current Descriptor Pointer
Bryan Wu1394f032007-05-06 14:50:22 -070082 register */
Bryan Wu452af712007-10-22 00:02:14 +080083 unsigned long curr_addr_ptr; /* DMA Current Address Pointer
Bryan Wu1394f032007-05-06 14:50:22 -070084 register */
85 unsigned short irq_status; /* DMA irq status register */
86 unsigned short dummy6;
87
88 unsigned short peripheral_map; /* DMA peripheral map register */
89 unsigned short dummy7;
90
91 unsigned short curr_x_count; /* DMA Current x-count register */
92 unsigned short dummy8;
93
94 unsigned long reserved2;
95
96 unsigned short curr_y_count; /* DMA Current y-count register */
97 unsigned short dummy9;
98
99 unsigned long reserved3;
100
101};
102
Bryan Wu1394f032007-05-06 14:50:22 -0700103struct dma_channel {
Michael McTernan99532fd2009-01-07 23:14:38 +0800104 const char *device_id;
Mike Frysingerd2e015d2009-10-09 22:18:12 +0000105 atomic_t chan_status;
Mike Frysinger4ce18732009-01-07 23:14:38 +0800106 volatile struct dma_register *regs;
Bryan Wu1394f032007-05-06 14:50:22 -0700107 struct dmasg *sg; /* large mode descriptor */
Michael Hennericha2ba8b12008-10-28 18:19:29 +0800108 unsigned int irq;
Bryan Wu1394f032007-05-06 14:50:22 -0700109 void *data;
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800110#ifdef CONFIG_PM
111 unsigned short saved_peripheral_map;
112#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700113};
114
Michael Hennerich1efc80b2008-07-19 16:57:32 +0800115#ifdef CONFIG_PM
116int blackfin_dma_suspend(void);
117void blackfin_dma_resume(void);
118#endif
119
Bryan Wu1394f032007-05-06 14:50:22 -0700120/*******************************************************************************
121* DMA API's
122*******************************************************************************/
Mike Frysinger9c417a42009-01-07 23:14:39 +0800123extern struct dma_channel dma_ch[MAX_DMA_CHANNELS];
124extern struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS];
125extern int channel2irq(unsigned int channel);
Bryan Wu1394f032007-05-06 14:50:22 -0700126
Mike Frysinger9c417a42009-01-07 23:14:39 +0800127static inline void set_dma_start_addr(unsigned int channel, unsigned long addr)
128{
129 dma_ch[channel].regs->start_addr = addr;
130}
Mike Frysinger6ab729d2009-01-07 23:14:38 +0800131static inline void set_dma_next_desc_addr(unsigned int channel, void *addr)
Mike Frysinger9c417a42009-01-07 23:14:39 +0800132{
133 dma_ch[channel].regs->next_desc_ptr = addr;
134}
Mike Frysinger6ab729d2009-01-07 23:14:38 +0800135static inline void set_dma_curr_desc_addr(unsigned int channel, void *addr)
Mike Frysinger9c417a42009-01-07 23:14:39 +0800136{
137 dma_ch[channel].regs->curr_desc_ptr = addr;
138}
139static inline void set_dma_x_count(unsigned int channel, unsigned short x_count)
140{
141 dma_ch[channel].regs->x_count = x_count;
142}
143static inline void set_dma_y_count(unsigned int channel, unsigned short y_count)
144{
145 dma_ch[channel].regs->y_count = y_count;
146}
147static inline void set_dma_x_modify(unsigned int channel, short x_modify)
148{
149 dma_ch[channel].regs->x_modify = x_modify;
150}
151static inline void set_dma_y_modify(unsigned int channel, short y_modify)
152{
153 dma_ch[channel].regs->y_modify = y_modify;
154}
155static inline void set_dma_config(unsigned int channel, unsigned short config)
156{
157 dma_ch[channel].regs->cfg = config;
158}
159static inline void set_dma_curr_addr(unsigned int channel, unsigned long addr)
160{
161 dma_ch[channel].regs->curr_addr_ptr = addr;
162}
Bryan Wu1394f032007-05-06 14:50:22 -0700163
Mike Frysinger9c417a42009-01-07 23:14:39 +0800164static inline unsigned short
165set_bfin_dma_config(char direction, char flow_mode,
166 char intr_mode, char dma_mode, char width, char syncmode)
167{
168 return (direction << 1) | (width << 2) | (dma_mode << 4) |
169 (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5);
170}
Bryan Wu1394f032007-05-06 14:50:22 -0700171
Mike Frysinger9c417a42009-01-07 23:14:39 +0800172static inline unsigned short get_dma_curr_irqstat(unsigned int channel)
173{
174 return dma_ch[channel].regs->irq_status;
175}
176static inline unsigned short get_dma_curr_xcount(unsigned int channel)
177{
178 return dma_ch[channel].regs->curr_x_count;
179}
180static inline unsigned short get_dma_curr_ycount(unsigned int channel)
181{
182 return dma_ch[channel].regs->curr_y_count;
183}
Mike Frysinger6ab729d2009-01-07 23:14:38 +0800184static inline void *get_dma_next_desc_ptr(unsigned int channel)
Mike Frysinger9c417a42009-01-07 23:14:39 +0800185{
186 return dma_ch[channel].regs->next_desc_ptr;
187}
Mike Frysinger6ab729d2009-01-07 23:14:38 +0800188static inline void *get_dma_curr_desc_ptr(unsigned int channel)
Mike Frysinger9c417a42009-01-07 23:14:39 +0800189{
190 return dma_ch[channel].regs->curr_desc_ptr;
191}
Mike Frysinger71f5ca32009-01-07 23:14:38 +0800192static inline unsigned short get_dma_config(unsigned int channel)
193{
194 return dma_ch[channel].regs->cfg;
195}
Mike Frysinger9c417a42009-01-07 23:14:39 +0800196static inline unsigned long get_dma_curr_addr(unsigned int channel)
197{
198 return dma_ch[channel].regs->curr_addr_ptr;
199}
Bryan Wu1394f032007-05-06 14:50:22 -0700200
Mike Frysinger9c417a42009-01-07 23:14:39 +0800201static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize)
202{
Sonic Zhangea8538a2009-06-01 00:49:32 -0400203 /* Make sure the internal data buffers in the core are drained
204 * so that the DMA descriptors are completely written when the
205 * DMA engine goes to fetch them below.
206 */
207 SSYNC();
208
209 dma_ch[channel].regs->next_desc_ptr = sg;
Mike Frysingerd41e8002009-01-07 23:14:38 +0800210 dma_ch[channel].regs->cfg =
211 (dma_ch[channel].regs->cfg & ~(0xf << 8)) |
212 ((ndsize & 0xf) << 8);
Mike Frysinger9c417a42009-01-07 23:14:39 +0800213}
214
215static inline int dma_channel_active(unsigned int channel)
216{
Mike Frysingerd2e015d2009-10-09 22:18:12 +0000217 return atomic_read(&dma_ch[channel].chan_status);
Mike Frysinger9c417a42009-01-07 23:14:39 +0800218}
219
220static inline void disable_dma(unsigned int channel)
221{
222 dma_ch[channel].regs->cfg &= ~DMAEN;
223 SSYNC();
Mike Frysinger9c417a42009-01-07 23:14:39 +0800224}
225static inline void enable_dma(unsigned int channel)
226{
227 dma_ch[channel].regs->curr_x_count = 0;
228 dma_ch[channel].regs->curr_y_count = 0;
229 dma_ch[channel].regs->cfg |= DMAEN;
Mike Frysinger9c417a42009-01-07 23:14:39 +0800230}
Bryan Wu1394f032007-05-06 14:50:22 -0700231void free_dma(unsigned int channel);
Michael McTernan99532fd2009-01-07 23:14:38 +0800232int request_dma(unsigned int channel, const char *device_id);
Mike Frysinger9c417a42009-01-07 23:14:39 +0800233int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data);
234
235static inline void dma_disable_irq(unsigned int channel)
236{
237 disable_irq(dma_ch[channel].irq);
238}
239static inline void dma_enable_irq(unsigned int channel)
240{
241 enable_irq(dma_ch[channel].irq);
242}
243static inline void clear_dma_irqstat(unsigned int channel)
244{
245 dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR;
246}
247
Bryan Wu1394f032007-05-06 14:50:22 -0700248void *dma_memcpy(void *dest, const void *src, size_t count);
249void *safe_dma_memcpy(void *dest, const void *src, size_t count);
Mike Frysingerdd3dd382009-01-07 23:14:39 +0800250void blackfin_dma_early_init(void);
Robin Getzfecbd732009-04-23 20:49:43 +0000251void early_dma_memcpy(void *dest, const void *src, size_t count);
252void early_dma_memcpy_done(void);
Bryan Wu1394f032007-05-06 14:50:22 -0700253
Bryan Wu1394f032007-05-06 14:50:22 -0700254#endif