Blame view

arch/arm/plat-omap/dma.c 51 KB
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1
2
3
  /*
   * linux/arch/arm/plat-omap/dma.c
   *
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
4
   * Copyright (C) 2003 - 2008 Nokia Corporation
96de0e252   Jan Engelhardt   Convert files to ...
5
   * Author: Juha Yrjölä <juha.yrjola@nokia.com>
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
6
7
8
   * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
   * Graphics DMA and LCD DMA graphics tranformations
   * by Imre Deak <imre.deak@nokia.com>
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
9
   * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
10
   * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com>
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
11
12
   * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
   *
44169075e   Santosh Shilimkar   ARM: OMAP4: Add m...
13
14
15
   * Copyright (C) 2009 Texas Instruments
   * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
   *
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
16
17
   * Support functions for the OMAP internal DMA channels.
   *
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
18
19
20
21
   * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
   * Converted DMA library into DMA platform driver.
   *	- G, Manjunath Kondaiah <manjugk@ti.com>
   *
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
22
23
24
25
26
27
28
29
30
31
32
33
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/sched.h>
  #include <linux/spinlock.h>
  #include <linux/errno.h>
  #include <linux/interrupt.h>
418ca1f0a   Thomas Gleixner   [ARM] 3701/1: ARM...
34
  #include <linux/irq.h>
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
35
  #include <linux/io.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
36
  #include <linux/slab.h>
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
37
  #include <linux/delay.h>
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
38
39
  
  #include <asm/system.h>
a09e64fbc   Russell King   [ARM] Move includ...
40
  #include <mach/hardware.h>
ce491cf85   Tony Lindgren   omap: headers: Mo...
41
  #include <plat/dma.h>
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
42

ce491cf85   Tony Lindgren   omap: headers: Mo...
43
  #include <plat/tc.h>
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
44

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
45
46
47
48
49
50
51
52
  #undef DEBUG
  
  #ifndef CONFIG_ARCH_OMAP1
  enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
  	DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
  };
  
  enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
53
  #endif
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
54

97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
55
  #define OMAP_DMA_ACTIVE			0x01
4fb699b40   Adrian Hunter   omap: DMA: clear ...
56
  #define OMAP2_DMA_CSR_CLEAR_MASK	0xffffffff
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
57

97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
58
  #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
59

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
60
61
  static struct omap_system_dma_plat_info *p;
  static struct omap_dma_dev_attr *d;
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
62
  static int enable_1510_mode;
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
63
  static u32 errata;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
64

f2d118582   Tero Kristo   OMAP: PM: DMA con...
65
66
67
68
69
  static struct omap_dma_global_context_registers {
  	u32 dma_irqenable_l0;
  	u32 dma_ocp_sysconfig;
  	u32 dma_gcr;
  } omap_dma_global_context;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
70
71
72
73
74
75
76
77
78
79
80
81
  struct dma_link_info {
  	int *linked_dmach_q;
  	int no_of_lchs_linked;
  
  	int q_count;
  	int q_tail;
  	int q_head;
  
  	int chain_state;
  	int chain_mode;
  
  };
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
82
83
84
  static struct dma_link_info *dma_linked_lch;
  
  #ifndef CONFIG_ARCH_OMAP1
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  
  /* Chain handling macros */
  #define OMAP_DMA_CHAIN_QINIT(chain_id)					\
  	do {								\
  		dma_linked_lch[chain_id].q_head =			\
  		dma_linked_lch[chain_id].q_tail =			\
  		dma_linked_lch[chain_id].q_count = 0;			\
  	} while (0)
  #define OMAP_DMA_CHAIN_QFULL(chain_id)					\
  		(dma_linked_lch[chain_id].no_of_lchs_linked ==		\
  		dma_linked_lch[chain_id].q_count)
  #define OMAP_DMA_CHAIN_QLAST(chain_id)					\
  	do {								\
  		((dma_linked_lch[chain_id].no_of_lchs_linked-1) ==	\
  		dma_linked_lch[chain_id].q_count)			\
  	} while (0)
  #define OMAP_DMA_CHAIN_QEMPTY(chain_id)					\
  		(0 == dma_linked_lch[chain_id].q_count)
  #define __OMAP_DMA_CHAIN_INCQ(end)					\
  	((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked)
  #define OMAP_DMA_CHAIN_INCQHEAD(chain_id)				\
  	do {								\
  		__OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head);	\
  		dma_linked_lch[chain_id].q_count--;			\
  	} while (0)
  
  #define OMAP_DMA_CHAIN_INCQTAIL(chain_id)				\
  	do {								\
  		__OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_tail);	\
  		dma_linked_lch[chain_id].q_count++; \
  	} while (0)
  #endif
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
117
118
  
  static int dma_lch_count;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
119
  static int dma_chan_count;
2263f0222   Santosh Shilimkar   ARM: OMAP: Get av...
120
  static int omap_dma_reserve_channels;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
121
122
  
  static spinlock_t dma_chan_lock;
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
123
  static struct omap_dma_lch *dma_chan;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
124

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
125
126
127
  static inline void disable_lnk(int lch);
  static void omap_disable_channel_irq(int lch);
  static inline void omap_enable_channel_irq(int lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
128
129
  #define REVISIT_24XX()		printk(KERN_ERR "FIXME: no %s on 24xx
  ", \
8e86f4271   Harvey Harrison   [ARM] replace rem...
130
  						__func__);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
131
132
133
  
  #ifdef CONFIG_ARCH_OMAP15XX
  /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
c77675827   Aaro Koskinen   arm: plat-omap: d...
134
  static int omap_dma_in_1510_mode(void)
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
135
136
137
138
139
140
141
142
  {
  	return enable_1510_mode;
  }
  #else
  #define omap_dma_in_1510_mode()		0
  #endif
  
  #ifdef CONFIG_ARCH_OMAP1
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  static inline int get_gdma_dev(int req)
  {
  	u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
  	int shift = ((req - 1) % 5) * 6;
  
  	return ((omap_readl(reg) >> shift) & 0x3f) + 1;
  }
  
  static inline void set_gdma_dev(int req, int dev)
  {
  	u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
  	int shift = ((req - 1) % 5) * 6;
  	u32 l;
  
  	l = omap_readl(reg);
  	l &= ~(0x3f << shift);
  	l |= (dev - 1) << shift;
  	omap_writel(l, reg);
  }
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
162
163
164
  #else
  #define set_gdma_dev(req, dev)	do {} while (0)
  #endif
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
165

709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
166
  void omap_set_dma_priority(int lch, int dst_port, int priority)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
167
168
169
  {
  	unsigned long reg;
  	u32 l;
709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  	if (cpu_class_is_omap1()) {
  		switch (dst_port) {
  		case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
  			reg = OMAP_TC_OCPT1_PRIOR;
  			break;
  		case OMAP_DMA_PORT_OCP_T2:	/* FFFECCD0 */
  			reg = OMAP_TC_OCPT2_PRIOR;
  			break;
  		case OMAP_DMA_PORT_EMIFF:	/* FFFECC08 */
  			reg = OMAP_TC_EMIFF_PRIOR;
  			break;
  		case OMAP_DMA_PORT_EMIFS:	/* FFFECC04 */
  			reg = OMAP_TC_EMIFS_PRIOR;
  			break;
  		default:
  			BUG();
  			return;
  		}
  		l = omap_readl(reg);
  		l &= ~(0xf << 8);
  		l |= (priority & 0xf) << 8;
  		omap_writel(l, reg);
  	}
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
193
  	if (cpu_class_is_omap2()) {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
194
  		u32 ccr;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
195
  		ccr = p->dma_read(CCR, lch);
709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
196
  		if (priority)
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
197
  			ccr |= (1 << 6);
709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
198
  		else
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
199
  			ccr &= ~(1 << 6);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
200
  		p->dma_write(ccr, CCR, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
201
  	}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
202
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
203
  EXPORT_SYMBOL(omap_set_dma_priority);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
204
205
  
  void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
206
207
  				  int frame_count, int sync_mode,
  				  int dma_trigger, int src_or_dst_synch)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
208
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
209
  	u32 l;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
210
  	l = p->dma_read(CSDP, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
211
212
  	l &= ~0x03;
  	l |= data_type;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
213
  	p->dma_write(l, CSDP, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
214

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
215
  	if (cpu_class_is_omap1()) {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
216
  		u16 ccr;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
217
  		ccr = p->dma_read(CCR, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
218
  		ccr &= ~(1 << 5);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
219
  		if (sync_mode == OMAP_DMA_SYNC_FRAME)
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
220
  			ccr |= 1 << 5;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
221
  		p->dma_write(ccr, CCR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
222

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
223
  		ccr = p->dma_read(CCR2, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
224
  		ccr &= ~(1 << 2);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
225
  		if (sync_mode == OMAP_DMA_SYNC_BLOCK)
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
226
  			ccr |= 1 << 2;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
227
  		p->dma_write(ccr, CCR2, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
228
  	}
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
229
  	if (cpu_class_is_omap2() && dma_trigger) {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
230
  		u32 val;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
231

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
232
  		val = p->dma_read(CCR, lch);
4b3cf4484   Anand Gadiyar   ARM: OMAP: Fix DM...
233
234
  
  		/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
72a1179ed   Samu Onkalo   omap: dma: Suppor...
235
  		val &= ~((1 << 23) | (3 << 19) | 0x1f);
4b3cf4484   Anand Gadiyar   ARM: OMAP: Fix DM...
236
237
  		val |= (dma_trigger & ~0x1f) << 14;
  		val |= dma_trigger & 0x1f;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
238

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
239
240
  		if (sync_mode & OMAP_DMA_SYNC_FRAME)
  			val |= 1 << 5;
eca9e56eb   Peter Ujfalusi   ARM: OMAP: DMA tr...
241
242
  		else
  			val &= ~(1 << 5);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
243

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
244
245
  		if (sync_mode & OMAP_DMA_SYNC_BLOCK)
  			val |= 1 << 18;
eca9e56eb   Peter Ujfalusi   ARM: OMAP: DMA tr...
246
247
  		else
  			val &= ~(1 << 18);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
248

72a1179ed   Samu Onkalo   omap: dma: Suppor...
249
250
251
252
  		if (src_or_dst_synch == OMAP_DMA_DST_SYNC_PREFETCH) {
  			val &= ~(1 << 24);	/* dest synch */
  			val |= (1 << 23);	/* Prefetch */
  		} else if (src_or_dst_synch) {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
253
  			val |= 1 << 24;		/* source synch */
72a1179ed   Samu Onkalo   omap: dma: Suppor...
254
  		} else {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
255
  			val &= ~(1 << 24);	/* dest synch */
72a1179ed   Samu Onkalo   omap: dma: Suppor...
256
  		}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
257
  		p->dma_write(val, CCR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
258
  	}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
259
260
  	p->dma_write(elem_count, CEN, lch);
  	p->dma_write(frame_count, CFN, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
261
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
262
  EXPORT_SYMBOL(omap_set_dma_transfer_params);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
263

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
264
265
  void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
  {
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
266
  	BUG_ON(omap_dma_in_1510_mode());
0815f8eaa   Tomi Valkeinen   ARM: OMAP2/3: DMA...
267
268
  	if (cpu_class_is_omap1()) {
  		u16 w;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
269

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
270
  		w = p->dma_read(CCR2, lch);
0815f8eaa   Tomi Valkeinen   ARM: OMAP2/3: DMA...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
  		w &= ~0x03;
  
  		switch (mode) {
  		case OMAP_DMA_CONSTANT_FILL:
  			w |= 0x01;
  			break;
  		case OMAP_DMA_TRANSPARENT_COPY:
  			w |= 0x02;
  			break;
  		case OMAP_DMA_COLOR_DIS:
  			break;
  		default:
  			BUG();
  		}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
285
  		p->dma_write(w, CCR2, lch);
0815f8eaa   Tomi Valkeinen   ARM: OMAP2/3: DMA...
286

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
287
  		w = p->dma_read(LCH_CTRL, lch);
0815f8eaa   Tomi Valkeinen   ARM: OMAP2/3: DMA...
288
289
290
  		w &= ~0x0f;
  		/* Default is channel type 2D */
  		if (mode) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
291
  			p->dma_write(color, COLOR, lch);
0815f8eaa   Tomi Valkeinen   ARM: OMAP2/3: DMA...
292
293
  			w |= 1;		/* Channel type G */
  		}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
294
  		p->dma_write(w, LCH_CTRL, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
295
  	}
0815f8eaa   Tomi Valkeinen   ARM: OMAP2/3: DMA...
296
297
298
  
  	if (cpu_class_is_omap2()) {
  		u32 val;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
299
  		val = p->dma_read(CCR, lch);
0815f8eaa   Tomi Valkeinen   ARM: OMAP2/3: DMA...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  		val &= ~((1 << 17) | (1 << 16));
  
  		switch (mode) {
  		case OMAP_DMA_CONSTANT_FILL:
  			val |= 1 << 16;
  			break;
  		case OMAP_DMA_TRANSPARENT_COPY:
  			val |= 1 << 17;
  			break;
  		case OMAP_DMA_COLOR_DIS:
  			break;
  		default:
  			BUG();
  		}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
314
  		p->dma_write(val, CCR, lch);
0815f8eaa   Tomi Valkeinen   ARM: OMAP2/3: DMA...
315
316
  
  		color &= 0xffffff;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
317
  		p->dma_write(color, COLOR, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
318
  	}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
319
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
320
  EXPORT_SYMBOL(omap_set_dma_color_mode);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
321

709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
322
323
  void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
  {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
324
  	if (cpu_class_is_omap2()) {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
325
  		u32 csdp;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
326
  		csdp = p->dma_read(CSDP, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
327
328
  		csdp &= ~(0x3 << 16);
  		csdp |= (mode << 16);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
329
  		p->dma_write(csdp, CSDP, lch);
709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
330
331
  	}
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
332
  EXPORT_SYMBOL(omap_set_dma_write_mode);
709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
333

0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
334
335
336
337
  void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
  {
  	if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
  		u32 l;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
338
  		l = p->dma_read(LCH_CTRL, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
339
340
  		l &= ~0x7;
  		l |= mode;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
341
  		p->dma_write(l, LCH_CTRL, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
342
343
344
  	}
  }
  EXPORT_SYMBOL(omap_set_dma_channel_mode);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
345
  /* Note that src_port is only for omap1 */
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
346
  void omap_set_dma_src_params(int lch, int src_port, int src_amode,
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
347
348
  			     unsigned long src_start,
  			     int src_ei, int src_fi)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
349
  {
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
350
  	u32 l;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
351
  	if (cpu_class_is_omap1()) {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
352
  		u16 w;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
353

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
354
  		w = p->dma_read(CSDP, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
355
356
  		w &= ~(0x1f << 2);
  		w |= src_port << 2;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
357
  		p->dma_write(w, CSDP, lch);
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
358
  	}
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
359

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
360
  	l = p->dma_read(CCR, lch);
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
361
362
  	l &= ~(0x03 << 12);
  	l |= src_amode << 12;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
363
  	p->dma_write(l, CCR, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
364

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
365
  	p->dma_write(src_start, CSSA, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
366

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
367
368
  	p->dma_write(src_ei, CSEI, lch);
  	p->dma_write(src_fi, CSFI, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
369
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
370
  EXPORT_SYMBOL(omap_set_dma_src_params);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
371

97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
372
  void omap_set_dma_params(int lch, struct omap_dma_channel_params *params)
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
373
374
375
376
377
378
379
380
381
382
383
384
  {
  	omap_set_dma_transfer_params(lch, params->data_type,
  				     params->elem_count, params->frame_count,
  				     params->sync_mode, params->trigger,
  				     params->src_or_dst_synch);
  	omap_set_dma_src_params(lch, params->src_port,
  				params->src_amode, params->src_start,
  				params->src_ei, params->src_fi);
  
  	omap_set_dma_dest_params(lch, params->dst_port,
  				 params->dst_amode, params->dst_start,
  				 params->dst_ei, params->dst_fi);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
385
386
387
  	if (params->read_prio || params->write_prio)
  		omap_dma_set_prio_lch(lch, params->read_prio,
  				      params->write_prio);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
388
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
389
  EXPORT_SYMBOL(omap_set_dma_params);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
390
391
392
  
  void omap_set_dma_src_index(int lch, int eidx, int fidx)
  {
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
393
  	if (cpu_class_is_omap2())
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
394
  		return;
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
395

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
396
397
  	p->dma_write(eidx, CSEI, lch);
  	p->dma_write(fidx, CSFI, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
398
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
399
  EXPORT_SYMBOL(omap_set_dma_src_index);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
400
401
402
  
  void omap_set_dma_src_data_pack(int lch, int enable)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
403
  	u32 l;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
404
  	l = p->dma_read(CSDP, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
405
  	l &= ~(1 << 6);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
406
  	if (enable)
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
407
  		l |= (1 << 6);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
408
  	p->dma_write(l, CSDP, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
409
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
410
  EXPORT_SYMBOL(omap_set_dma_src_data_pack);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
411
412
413
  
  void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
  {
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
414
  	unsigned int burst = 0;
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
415
  	u32 l;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
416
  	l = p->dma_read(CSDP, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
417
  	l &= ~(0x03 << 7);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
418

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
419
420
421
422
  	switch (burst_mode) {
  	case OMAP_DMA_DATA_BURST_DIS:
  		break;
  	case OMAP_DMA_DATA_BURST_4:
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
423
  		if (cpu_class_is_omap2())
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
424
425
426
  			burst = 0x1;
  		else
  			burst = 0x2;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
427
428
  		break;
  	case OMAP_DMA_DATA_BURST_8:
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
429
  		if (cpu_class_is_omap2()) {
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
430
431
432
  			burst = 0x2;
  			break;
  		}
ea221a6ae   manjugk manjugk   omap: DMA: Fix mu...
433
434
  		/*
  		 * not supported by current hardware on OMAP1
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
435
436
437
  		 * w |= (0x03 << 7);
  		 * fall through
  		 */
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
438
  	case OMAP_DMA_DATA_BURST_16:
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
439
  		if (cpu_class_is_omap2()) {
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
440
441
442
  			burst = 0x3;
  			break;
  		}
ea221a6ae   manjugk manjugk   omap: DMA: Fix mu...
443
444
  		/*
  		 * OMAP1 don't support burst 16
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
445
446
  		 * fall through
  		 */
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
447
448
449
  	default:
  		BUG();
  	}
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
450
451
  
  	l |= (burst << 7);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
452
  	p->dma_write(l, CSDP, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
453
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
454
  EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
455

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
456
  /* Note that dest_port is only for OMAP1 */
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
457
  void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
458
459
  			      unsigned long dest_start,
  			      int dst_ei, int dst_fi)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
460
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
461
  	u32 l;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
462
  	if (cpu_class_is_omap1()) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
463
  		l = p->dma_read(CSDP, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
464
465
  		l &= ~(0x1f << 9);
  		l |= dest_port << 9;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
466
  		p->dma_write(l, CSDP, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
467
  	}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
468

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
469
  	l = p->dma_read(CCR, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
470
471
  	l &= ~(0x03 << 14);
  	l |= dest_amode << 14;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
472
  	p->dma_write(l, CCR, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
473

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
474
  	p->dma_write(dest_start, CDSA, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
475

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
476
477
  	p->dma_write(dst_ei, CDEI, lch);
  	p->dma_write(dst_fi, CDFI, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
478
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
479
  EXPORT_SYMBOL(omap_set_dma_dest_params);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
480
481
482
  
  void omap_set_dma_dest_index(int lch, int eidx, int fidx)
  {
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
483
  	if (cpu_class_is_omap2())
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
484
  		return;
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
485

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
486
487
  	p->dma_write(eidx, CDEI, lch);
  	p->dma_write(fidx, CDFI, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
488
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
489
  EXPORT_SYMBOL(omap_set_dma_dest_index);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
490
491
492
  
  void omap_set_dma_dest_data_pack(int lch, int enable)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
493
  	u32 l;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
494
  	l = p->dma_read(CSDP, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
495
  	l &= ~(1 << 13);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
496
  	if (enable)
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
497
  		l |= 1 << 13;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
498
  	p->dma_write(l, CSDP, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
499
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
500
  EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
501
502
503
  
  void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
  {
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
504
  	unsigned int burst = 0;
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
505
  	u32 l;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
506
  	l = p->dma_read(CSDP, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
507
  	l &= ~(0x03 << 14);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
508

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
509
510
511
512
  	switch (burst_mode) {
  	case OMAP_DMA_DATA_BURST_DIS:
  		break;
  	case OMAP_DMA_DATA_BURST_4:
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
513
  		if (cpu_class_is_omap2())
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
514
515
516
  			burst = 0x1;
  		else
  			burst = 0x2;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
517
518
  		break;
  	case OMAP_DMA_DATA_BURST_8:
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
519
  		if (cpu_class_is_omap2())
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
520
521
522
  			burst = 0x2;
  		else
  			burst = 0x3;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
523
  		break;
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
524
  	case OMAP_DMA_DATA_BURST_16:
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
525
  		if (cpu_class_is_omap2()) {
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
526
527
528
  			burst = 0x3;
  			break;
  		}
ea221a6ae   manjugk manjugk   omap: DMA: Fix mu...
529
530
  		/*
  		 * OMAP1 don't support burst 16
6dc3c8f20   Kyungmin Park   ARM: OMAP: OMAP2 ...
531
532
  		 * fall through
  		 */
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
533
534
535
536
537
538
  	default:
  		printk(KERN_ERR "Invalid DMA burst mode
  ");
  		BUG();
  		return;
  	}
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
539
  	l |= (burst << 14);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
540
  	p->dma_write(l, CSDP, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
541
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
542
  EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
543

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
544
  static inline void omap_enable_channel_irq(int lch)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
545
  {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
546
  	u32 status;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
547

7ff879dbc   Tony Lindgren   ARM: OMAP: Fix DM...
548
549
  	/* Clear CSR */
  	if (cpu_class_is_omap1())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
550
  		status = p->dma_read(CSR, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
551
  	else if (cpu_class_is_omap2())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
552
  		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
553

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
554
  	/* Enable some nice interrupts. */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
555
  	p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
556
  }
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
557
  static void omap_disable_channel_irq(int lch)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
558
  {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
559
  	if (cpu_class_is_omap2())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
560
  		p->dma_write(0, CICR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
561
562
563
564
565
566
  }
  
  void omap_enable_dma_irq(int lch, u16 bits)
  {
  	dma_chan[lch].enabled_irqs |= bits;
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
567
  EXPORT_SYMBOL(omap_enable_dma_irq);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
568

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
569
570
571
572
  void omap_disable_dma_irq(int lch, u16 bits)
  {
  	dma_chan[lch].enabled_irqs &= ~bits;
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
573
  EXPORT_SYMBOL(omap_disable_dma_irq);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
574
575
576
  
  static inline void enable_lnk(int lch)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
577
  	u32 l;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
578
  	l = p->dma_read(CLNK_CTRL, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
579

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
580
  	if (cpu_class_is_omap1())
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
581
  		l &= ~(1 << 14);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
582

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
583
  	/* Set the ENABLE_LNK bits */
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
584
  	if (dma_chan[lch].next_lch != -1)
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
585
  		l = dma_chan[lch].next_lch | (1 << 15);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
586
587
  
  #ifndef CONFIG_ARCH_OMAP1
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
588
589
590
  	if (cpu_class_is_omap2())
  		if (dma_chan[lch].next_linked_ch != -1)
  			l = dma_chan[lch].next_linked_ch | (1 << 15);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
591
  #endif
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
592

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
593
  	p->dma_write(l, CLNK_CTRL, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
594
595
596
597
  }
  
  static inline void disable_lnk(int lch)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
598
  	u32 l;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
599
  	l = p->dma_read(CLNK_CTRL, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
600

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
601
  	/* Disable interrupts */
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
602
  	if (cpu_class_is_omap1()) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
603
  		p->dma_write(0, CICR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
604
  		/* Set the STOP_LNK bit */
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
605
  		l |= 1 << 14;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
606
  	}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
607

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
608
  	if (cpu_class_is_omap2()) {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
609
610
  		omap_disable_channel_irq(lch);
  		/* Clear the ENABLE_LNK bit */
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
611
  		l &= ~(1 << 15);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
612
  	}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
613

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
614
  	p->dma_write(l, CLNK_CTRL, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
615
616
  	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
  }
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
617
  static inline void omap2_enable_irq_lch(int lch)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
618
  {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
619
  	u32 val;
ee9073245   Tao Hu   omap: Fix race co...
620
  	unsigned long flags;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
621

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
622
  	if (!cpu_class_is_omap2())
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
623
  		return;
ee9073245   Tao Hu   omap: Fix race co...
624
  	spin_lock_irqsave(&dma_chan_lock, flags);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
625
  	val = p->dma_read(IRQENABLE_L0, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
626
  	val |= 1 << lch;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
627
  	p->dma_write(val, IRQENABLE_L0, lch);
ee9073245   Tao Hu   omap: Fix race co...
628
  	spin_unlock_irqrestore(&dma_chan_lock, flags);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
629
  }
ada8d4a5e   Mika Westerberg   OMAP2/3/4: DMA: d...
630
631
632
633
634
635
636
637
638
  static inline void omap2_disable_irq_lch(int lch)
  {
  	u32 val;
  	unsigned long flags;
  
  	if (!cpu_class_is_omap2())
  		return;
  
  	spin_lock_irqsave(&dma_chan_lock, flags);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
639
  	val = p->dma_read(IRQENABLE_L0, lch);
ada8d4a5e   Mika Westerberg   OMAP2/3/4: DMA: d...
640
  	val &= ~(1 << lch);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
641
  	p->dma_write(val, IRQENABLE_L0, lch);
ada8d4a5e   Mika Westerberg   OMAP2/3/4: DMA: d...
642
643
  	spin_unlock_irqrestore(&dma_chan_lock, flags);
  }
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
644
  int omap_request_dma(int dev_id, const char *dev_name,
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
645
  		     void (*callback)(int lch, u16 ch_status, void *data),
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
  		     void *data, int *dma_ch_out)
  {
  	int ch, free_ch = -1;
  	unsigned long flags;
  	struct omap_dma_lch *chan;
  
  	spin_lock_irqsave(&dma_chan_lock, flags);
  	for (ch = 0; ch < dma_chan_count; ch++) {
  		if (free_ch == -1 && dma_chan[ch].dev_id == -1) {
  			free_ch = ch;
  			if (dev_id == 0)
  				break;
  		}
  	}
  	if (free_ch == -1) {
  		spin_unlock_irqrestore(&dma_chan_lock, flags);
  		return -EBUSY;
  	}
  	chan = dma_chan + free_ch;
  	chan->dev_id = dev_id;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
666
667
  	if (p->clear_lch_regs)
  		p->clear_lch_regs(free_ch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
668

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
669
  	if (cpu_class_is_omap2())
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
670
671
672
673
674
675
676
  		omap_clear_dma(free_ch);
  
  	spin_unlock_irqrestore(&dma_chan_lock, flags);
  
  	chan->dev_name = dev_name;
  	chan->callback = callback;
  	chan->data = data;
a92fda194   Jarkko Nikula   ARM: OMAP: DMA: F...
677
  	chan->flags = 0;
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
678

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
679
  #ifndef CONFIG_ARCH_OMAP1
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
680
681
682
683
  	if (cpu_class_is_omap2()) {
  		chan->chain_id = -1;
  		chan->next_linked_ch = -1;
  	}
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
684
  #endif
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
685

7ff879dbc   Tony Lindgren   ARM: OMAP: Fix DM...
686
  	chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
687

7ff879dbc   Tony Lindgren   ARM: OMAP: Fix DM...
688
689
  	if (cpu_class_is_omap1())
  		chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
690
  	else if (cpu_class_is_omap2())
7ff879dbc   Tony Lindgren   ARM: OMAP: Fix DM...
691
692
  		chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
  			OMAP2_DMA_TRANS_ERR_IRQ;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
693
694
695
696
697
698
699
  
  	if (cpu_is_omap16xx()) {
  		/* If the sync device is set, configure it dynamically. */
  		if (dev_id != 0) {
  			set_gdma_dev(free_ch + 1, dev_id);
  			dev_id = free_ch + 1;
  		}
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
700
701
702
703
  		/*
  		 * Disable the 1510 compatibility mode and set the sync device
  		 * id.
  		 */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
704
  		p->dma_write(dev_id | (1 << 10), CCR, free_ch);
557096fe2   Zebediah C. McClure   [OMAP850] Changes...
705
  	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
706
  		p->dma_write(dev_id, CCR, free_ch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
707
  	}
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
708
  	if (cpu_class_is_omap2()) {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
709
  		omap2_enable_irq_lch(free_ch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
710
711
  		omap_enable_channel_irq(free_ch);
  		/* Clear the CSR register and IRQ status register */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
712
713
  		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch);
  		p->dma_write(1 << free_ch, IRQSTATUS_L0, 0);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
714
715
716
717
718
719
  	}
  
  	*dma_ch_out = free_ch;
  
  	return 0;
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
720
  EXPORT_SYMBOL(omap_request_dma);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
721
722
723
724
  
  void omap_free_dma(int lch)
  {
  	unsigned long flags;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
725
  	if (dma_chan[lch].dev_id == -1) {
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
726
727
  		pr_err("omap_dma: trying to free unallocated DMA channel %d
  ",
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
728
  		       lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
729
730
  		return;
  	}
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
731

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
732
733
  	if (cpu_class_is_omap1()) {
  		/* Disable all DMA interrupts for the channel. */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
734
  		p->dma_write(0, CICR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
735
  		/* Make sure the DMA transfer is stopped. */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
736
  		p->dma_write(0, CCR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
737
  	}
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
738
  	if (cpu_class_is_omap2()) {
ada8d4a5e   Mika Westerberg   OMAP2/3/4: DMA: d...
739
  		omap2_disable_irq_lch(lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
740
741
  
  		/* Clear the CSR register and IRQ status register */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
742
743
  		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
  		p->dma_write(1 << lch, IRQSTATUS_L0, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
744
745
  
  		/* Disable all DMA interrupts for the channel. */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
746
  		p->dma_write(0, CICR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
747
748
  
  		/* Make sure the DMA transfer is stopped. */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
749
  		p->dma_write(0, CCR, lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
750
751
  		omap_clear_dma(lch);
  	}
da1b94e6a   Santosh Shilimkar   ARM: OMAP: Fix fo...
752
753
754
755
756
757
  
  	spin_lock_irqsave(&dma_chan_lock, flags);
  	dma_chan[lch].dev_id = -1;
  	dma_chan[lch].next_lch = -1;
  	dma_chan[lch].callback = NULL;
  	spin_unlock_irqrestore(&dma_chan_lock, flags);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
758
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
759
  EXPORT_SYMBOL(omap_free_dma);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
760

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
761
762
763
764
765
  /**
   * @brief omap_dma_set_global_params : Set global priority settings for dma
   *
   * @param arb_rate
   * @param max_fifo_depth
70cf644c3   Anuj Aggarwal   omap: SDMA: Fixin...
766
767
768
769
   * @param tparams - Number of threads to reserve : DMA_THREAD_RESERVE_NORM
   * 						   DMA_THREAD_RESERVE_ONET
   * 						   DMA_THREAD_RESERVE_TWOT
   * 						   DMA_THREAD_RESERVE_THREET
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
770
771
772
773
774
775
776
   */
  void
  omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
  {
  	u32 reg;
  
  	if (!cpu_class_is_omap2()) {
8e86f4271   Harvey Harrison   [ARM] replace rem...
777
778
  		printk(KERN_ERR "FIXME: no %s on 15xx/16xx
  ", __func__);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
779
780
  		return;
  	}
70cf644c3   Anuj Aggarwal   omap: SDMA: Fixin...
781
782
  	if (max_fifo_depth == 0)
  		max_fifo_depth = 1;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
783
784
  	if (arb_rate == 0)
  		arb_rate = 1;
70cf644c3   Anuj Aggarwal   omap: SDMA: Fixin...
785
786
787
  	reg = 0xff & max_fifo_depth;
  	reg |= (0x3 & tparams) << 12;
  	reg |= (arb_rate & 0xff) << 16;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
788

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
789
  	p->dma_write(reg, GCR, 0);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  }
  EXPORT_SYMBOL(omap_dma_set_global_params);
  
  /**
   * @brief omap_dma_set_prio_lch : Set channel wise priority settings
   *
   * @param lch
   * @param read_prio - Read priority
   * @param write_prio - Write priority
   * Both of the above can be set with one of the following values :
   * 	DMA_CH_PRIO_HIGH/DMA_CH_PRIO_LOW
   */
  int
  omap_dma_set_prio_lch(int lch, unsigned char read_prio,
  		      unsigned char write_prio)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
806
  	u32 l;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
807

4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
808
  	if (unlikely((lch < 0 || lch >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
809
810
811
812
  		printk(KERN_ERR "Invalid channel id
  ");
  		return -EINVAL;
  	}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
813
  	l = p->dma_read(CCR, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
814
  	l &= ~((1 << 6) | (1 << 26));
44169075e   Santosh Shilimkar   ARM: OMAP4: Add m...
815
  	if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
816
  		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
817
  	else
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
818
  		l |= ((read_prio & 0x1) << 6);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
819
  	p->dma_write(l, CCR, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
820

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
821
822
823
  	return 0;
  }
  EXPORT_SYMBOL(omap_dma_set_prio_lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
824
825
826
827
828
829
830
831
832
  /*
   * Clears any DMA state so the DMA engine is ready to restart with new buffers
   * through omap_start_dma(). Any buffers in flight are discarded.
   */
  void omap_clear_dma(int lch)
  {
  	unsigned long flags;
  
  	local_irq_save(flags);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
833
  	p->clear_dma(lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
834
835
  	local_irq_restore(flags);
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
836
  EXPORT_SYMBOL(omap_clear_dma);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
837
838
839
  
  void omap_start_dma(int lch)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
840
  	u32 l;
519e61666   manjugk manjugk   omap: DMA: Init C...
841
842
843
844
845
  	/*
  	 * The CPC/CDAC register needs to be initialized to zero
  	 * before starting dma transfer.
  	 */
  	if (cpu_is_omap15xx())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
846
  		p->dma_write(0, CPC, lch);
519e61666   manjugk manjugk   omap: DMA: Init C...
847
  	else
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
848
  		p->dma_write(0, CDAC, lch);
519e61666   manjugk manjugk   omap: DMA: Init C...
849

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
850
851
  	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
  		int next_lch, cur_lch;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
852
  		char dma_chan_link_map[dma_lch_count];
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
853
854
855
856
857
858
859
860
861
  
  		dma_chan_link_map[lch] = 1;
  		/* Set the link register of the first channel */
  		enable_lnk(lch);
  
  		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
  		cur_lch = dma_chan[lch].next_lch;
  		do {
  			next_lch = dma_chan[cur_lch].next_lch;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
862
  			/* The loop case: we've been here already */
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
863
864
865
866
867
868
  			if (dma_chan_link_map[cur_lch])
  				break;
  			/* Mark the current channel */
  			dma_chan_link_map[cur_lch] = 1;
  
  			enable_lnk(cur_lch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
869
  			omap_enable_channel_irq(cur_lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
870
871
872
  
  			cur_lch = next_lch;
  		} while (next_lch != -1);
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
873
  	} else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
874
  		p->dma_write(lch, CLNK_CTRL, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
875

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
876
  	omap_enable_channel_irq(lch);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
877
  	l = p->dma_read(CCR, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
878

d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
879
880
  	if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
  			l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
881
  	l |= OMAP_DMA_CCR_EN;
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
882

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
883
  	p->dma_write(l, CCR, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
884

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
885
886
  	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
887
  EXPORT_SYMBOL(omap_start_dma);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
888
889
890
  
  void omap_stop_dma(int lch)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
891
  	u32 l;
9da65a99e   Santosh Shilimkar   omap: SDMA: Fix o...
892
893
  	/* Disable all interrupts on the channel */
  	if (cpu_class_is_omap1())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
894
  		p->dma_write(0, CICR, lch);
9da65a99e   Santosh Shilimkar   omap: SDMA: Fix o...
895

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
896
  	l = p->dma_read(CCR, lch);
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
897
898
  	if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
  			(l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
899
900
901
902
  		int i = 0;
  		u32 sys_cf;
  
  		/* Configure No-Standby */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
903
  		l = p->dma_read(OCP_SYSCONFIG, lch);
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
904
905
906
  		sys_cf = l;
  		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
  		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
907
  		p->dma_write(l , OCP_SYSCONFIG, 0);
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
908

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
909
  		l = p->dma_read(CCR, lch);
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
910
  		l &= ~OMAP_DMA_CCR_EN;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
911
  		p->dma_write(l, CCR, lch);
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
912
913
  
  		/* Wait for sDMA FIFO drain */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
914
  		l = p->dma_read(CCR, lch);
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
915
916
917
918
  		while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
  					OMAP_DMA_CCR_WR_ACTIVE))) {
  			udelay(5);
  			i++;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
919
  			l = p->dma_read(CCR, lch);
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
920
921
922
923
924
925
  		}
  		if (i >= 100)
  			printk(KERN_ERR "DMA drain did not complete on "
  					"lch %d
  ", lch);
  		/* Restore OCP_SYSCONFIG */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
926
  		p->dma_write(sys_cf, OCP_SYSCONFIG, lch);
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
927
928
  	} else {
  		l &= ~OMAP_DMA_CCR_EN;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
929
  		p->dma_write(l, CCR, lch);
0e4905c01   Peter Ujfalusi   OMAP3: DMA: Errat...
930
  	}
9da65a99e   Santosh Shilimkar   omap: SDMA: Fix o...
931

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
932
933
  	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
  		int next_lch, cur_lch = lch;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
934
  		char dma_chan_link_map[dma_lch_count];
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
935
936
937
938
939
940
941
942
943
944
945
946
947
948
  
  		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
  		do {
  			/* The loop case: we've been here already */
  			if (dma_chan_link_map[cur_lch])
  				break;
  			/* Mark the current channel */
  			dma_chan_link_map[cur_lch] = 1;
  
  			disable_lnk(cur_lch);
  
  			next_lch = dma_chan[cur_lch].next_lch;
  			cur_lch = next_lch;
  		} while (next_lch != -1);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
949
  	}
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
950

5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
951
952
  	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
953
  EXPORT_SYMBOL(omap_stop_dma);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
954

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
955
  /*
709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
956
957
958
959
   * Allows changing the DMA callback function or data. This may be needed if
   * the driver shares a single DMA channel for multiple dma triggers.
   */
  int omap_set_dma_callback(int lch,
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
960
  			  void (*callback)(int lch, u16 ch_status, void *data),
709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
  			  void *data)
  {
  	unsigned long flags;
  
  	if (lch < 0)
  		return -ENODEV;
  
  	spin_lock_irqsave(&dma_chan_lock, flags);
  	if (dma_chan[lch].dev_id == -1) {
  		printk(KERN_ERR "DMA callback for not set for free channel
  ");
  		spin_unlock_irqrestore(&dma_chan_lock, flags);
  		return -EINVAL;
  	}
  	dma_chan[lch].callback = callback;
  	dma_chan[lch].data = data;
  	spin_unlock_irqrestore(&dma_chan_lock, flags);
  
  	return 0;
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
981
  EXPORT_SYMBOL(omap_set_dma_callback);
709eb3e5c   Tony Lindgren   ARM: OMAP: Sync D...
982
983
  
  /*
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
984
985
986
987
   * Returns current physical source address for the given DMA channel.
   * If the channel is running the caller must disable interrupts prior calling
   * this function and process the returned value before re-enabling interrupt to
   * prevent races with the interrupt handler. Note that in continuous mode there
25985edce   Lucas De Marchi   Fix common misspe...
988
   * is a chance for CSSA_L register overflow between the two reads resulting
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
989
990
991
   * in incorrect return value.
   */
  dma_addr_t omap_get_dma_src_pos(int lch)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
992
  {
0695de325   Tony Lindgren   ARM: OMAP: Fix wa...
993
  	dma_addr_t offset = 0;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
994

0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
995
  	if (cpu_is_omap15xx())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
996
  		offset = p->dma_read(CPC, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
997
  	else
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
998
  		offset = p->dma_read(CSAC, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
999

d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1000
  	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1001
  		offset = p->dma_read(CSAC, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1002

7ba966804   Peter Ujfalusi   ARM: OMAP2+: DMA:...
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
  	if (!cpu_is_omap15xx()) {
  		/*
  		 * CDAC == 0 indicates that the DMA transfer on the channel has
  		 * not been started (no data has been transferred so far).
  		 * Return the programmed source start address in this case.
  		 */
  		if (likely(p->dma_read(CDAC, lch)))
  			offset = p->dma_read(CSAC, lch);
  		else
  			offset = p->dma_read(CSSA, lch);
  	}
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1014
  	if (cpu_class_is_omap1())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1015
  		offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1016

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1017
  	return offset;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1018
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1019
  EXPORT_SYMBOL(omap_get_dma_src_pos);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1020

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1021
1022
1023
1024
1025
  /*
   * Returns current physical destination address for the given DMA channel.
   * If the channel is running the caller must disable interrupts prior calling
   * this function and process the returned value before re-enabling interrupt to
   * prevent races with the interrupt handler. Note that in continuous mode there
25985edce   Lucas De Marchi   Fix common misspe...
1026
   * is a chance for CDSA_L register overflow between the two reads resulting
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1027
1028
1029
   * in incorrect return value.
   */
  dma_addr_t omap_get_dma_dst_pos(int lch)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1030
  {
0695de325   Tony Lindgren   ARM: OMAP: Fix wa...
1031
  	dma_addr_t offset = 0;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1032

0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1033
  	if (cpu_is_omap15xx())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1034
  		offset = p->dma_read(CPC, lch);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1035
  	else
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1036
  		offset = p->dma_read(CDAC, lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1037

0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1038
1039
1040
1041
  	/*
  	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
  	 * read before the DMA controller finished disabling the channel.
  	 */
06e8077b5   Peter Ujfalusi   ARM: OMAP2+: DMA:...
1042
  	if (!cpu_is_omap15xx() && offset == 0) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1043
  		offset = p->dma_read(CDAC, lch);
06e8077b5   Peter Ujfalusi   ARM: OMAP2+: DMA:...
1044
1045
1046
1047
1048
1049
1050
1051
  		/*
  		 * CDAC == 0 indicates that the DMA transfer on the channel has
  		 * not been started (no data has been transferred so far).
  		 * Return the programmed destination start address in this case.
  		 */
  		if (unlikely(!offset))
  			offset = p->dma_read(CDSA, lch);
  	}
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1052
1053
  
  	if (cpu_class_is_omap1())
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1054
  		offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1055

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1056
  	return offset;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1057
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1058
  EXPORT_SYMBOL(omap_get_dma_dst_pos);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1059
1060
1061
  
  int omap_get_dma_active_status(int lch)
  {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1062
  	return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1063
  }
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1064
  EXPORT_SYMBOL(omap_get_dma_active_status);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1065

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1066
  int omap_dma_running(void)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1067
  {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1068
  	int lch;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1069

f8e9e9845   Janusz Krzysztofik   omap1: DMA: move ...
1070
1071
  	if (cpu_class_is_omap1())
  		if (omap_lcd_dma_running())
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1072
  			return 1;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1073

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1074
  	for (lch = 0; lch < dma_chan_count; lch++)
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1075
  		if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN)
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1076
  			return 1;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1077

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1078
  	return 0;
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1079
1080
1081
1082
1083
1084
1085
  }
  
  /*
   * lch_queue DMA will start right after lch_head one is finished.
   * For this DMA link to start, you still need to start (see omap_start_dma)
   * the first one. That will fire up the entire queue.
   */
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1086
  void omap_dma_link_lch(int lch_head, int lch_queue)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1087
1088
  {
  	if (omap_dma_in_1510_mode()) {
9f0f4ae57   Janusz Krzysztofik   ARM: OMAP: DMA: A...
1089
  		if (lch_head == lch_queue) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1090
  			p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8),
a4c537c7f   G, Manjunath Kondaiah   OMAP: DMA: Replac...
1091
  								CCR, lch_head);
9f0f4ae57   Janusz Krzysztofik   ARM: OMAP: DMA: A...
1092
1093
  			return;
  		}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1094
1095
1096
1097
1098
1099
1100
1101
  		printk(KERN_ERR "DMA linking is not supported in 1510 mode
  ");
  		BUG();
  		return;
  	}
  
  	if ((dma_chan[lch_head].dev_id == -1) ||
  	    (dma_chan[lch_queue].dev_id == -1)) {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1102
1103
1104
  		printk(KERN_ERR "omap_dma: trying to link "
  		       "non requested channels
  ");
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1105
1106
1107
1108
1109
  		dump_stack();
  	}
  
  	dma_chan[lch_head].next_lch = lch_queue;
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1110
  EXPORT_SYMBOL(omap_dma_link_lch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1111
1112
1113
1114
  
  /*
   * Once the DMA queue is stopped, we can destroy it.
   */
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1115
  void omap_dma_unlink_lch(int lch_head, int lch_queue)
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1116
1117
  {
  	if (omap_dma_in_1510_mode()) {
9f0f4ae57   Janusz Krzysztofik   ARM: OMAP: DMA: A...
1118
  		if (lch_head == lch_queue) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1119
  			p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8),
a4c537c7f   G, Manjunath Kondaiah   OMAP: DMA: Replac...
1120
  								CCR, lch_head);
9f0f4ae57   Janusz Krzysztofik   ARM: OMAP: DMA: A...
1121
1122
  			return;
  		}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1123
1124
1125
1126
1127
1128
1129
1130
  		printk(KERN_ERR "DMA linking is not supported in 1510 mode
  ");
  		BUG();
  		return;
  	}
  
  	if (dma_chan[lch_head].next_lch != lch_queue ||
  	    dma_chan[lch_head].next_lch == -1) {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1131
1132
1133
  		printk(KERN_ERR "omap_dma: trying to unlink "
  		       "non linked channels
  ");
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1134
1135
  		dump_stack();
  	}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1136
  	if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) ||
247421fda   Roel Kluin   OMAP: dma_chan[lc...
1137
  	    (dma_chan[lch_queue].flags & OMAP_DMA_ACTIVE)) {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1138
1139
1140
  		printk(KERN_ERR "omap_dma: You need to stop the DMA channels "
  		       "before unlinking
  ");
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1141
1142
1143
1144
1145
  		dump_stack();
  	}
  
  	dma_chan[lch_head].next_lch = -1;
  }
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1146
  EXPORT_SYMBOL(omap_dma_unlink_lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1147
1148
1149
1150
  #ifndef CONFIG_ARCH_OMAP1
  /* Create chain of DMA channesls */
  static void create_dma_lch_chain(int lch_head, int lch_queue)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1151
  	u32 l;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
  
  	/* Check if this is the first link in chain */
  	if (dma_chan[lch_head].next_linked_ch == -1) {
  		dma_chan[lch_head].next_linked_ch = lch_queue;
  		dma_chan[lch_head].prev_linked_ch = lch_queue;
  		dma_chan[lch_queue].next_linked_ch = lch_head;
  		dma_chan[lch_queue].prev_linked_ch = lch_head;
  	}
  
  	/* a link exists, link the new channel in circular chain */
  	else {
  		dma_chan[lch_queue].next_linked_ch =
  					dma_chan[lch_head].next_linked_ch;
  		dma_chan[lch_queue].prev_linked_ch = lch_head;
  		dma_chan[lch_head].next_linked_ch = lch_queue;
  		dma_chan[dma_chan[lch_queue].next_linked_ch].prev_linked_ch =
  					lch_queue;
  	}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1170
  	l = p->dma_read(CLNK_CTRL, lch_head);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1171
1172
  	l &= ~(0x1f);
  	l |= lch_queue;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1173
  	p->dma_write(l, CLNK_CTRL, lch_head);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1174

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1175
  	l = p->dma_read(CLNK_CTRL, lch_queue);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1176
1177
  	l &= ~(0x1f);
  	l |= (dma_chan[lch_queue].next_linked_ch);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1178
  	p->dma_write(l, CLNK_CTRL, lch_queue);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
  }
  
  /**
   * @brief omap_request_dma_chain : Request a chain of DMA channels
   *
   * @param dev_id - Device id using the dma channel
   * @param dev_name - Device name
   * @param callback - Call back function
   * @chain_id -
   * @no_of_chans - Number of channels requested
   * @chain_mode - Dynamic or static chaining : OMAP_DMA_STATIC_CHAIN
   * 					      OMAP_DMA_DYNAMIC_CHAIN
   * @params - Channel parameters
   *
af901ca18   André Goddard Rosa   tree-wide: fix as...
1193
   * @return - Success : 0
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1194
1195
1196
   * 	     Failure: -EINVAL/-ENOMEM
   */
  int omap_request_dma_chain(int dev_id, const char *dev_name,
279b918d7   Santosh Shilimkar   ARM: OMAP2/3: sDM...
1197
  			   void (*callback) (int lch, u16 ch_status,
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
  					     void *data),
  			   int *chain_id, int no_of_chans, int chain_mode,
  			   struct omap_dma_channel_params params)
  {
  	int *channels;
  	int i, err;
  
  	/* Is the chain mode valid ? */
  	if (chain_mode != OMAP_DMA_STATIC_CHAIN
  			&& chain_mode != OMAP_DMA_DYNAMIC_CHAIN) {
  		printk(KERN_ERR "Invalid chain mode requested
  ");
  		return -EINVAL;
  	}
  
  	if (unlikely((no_of_chans < 1
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1214
  			|| no_of_chans > dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1215
1216
1217
1218
  		printk(KERN_ERR "Invalid Number of channels requested
  ");
  		return -EINVAL;
  	}
ea221a6ae   manjugk manjugk   omap: DMA: Fix mu...
1219
1220
1221
1222
  	/*
  	 * Allocate a queue to maintain the status of the channels
  	 * in the chain
  	 */
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
  	channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL);
  	if (channels == NULL) {
  		printk(KERN_ERR "omap_dma: No memory for channel queue
  ");
  		return -ENOMEM;
  	}
  
  	/* request and reserve DMA channels for the chain */
  	for (i = 0; i < no_of_chans; i++) {
  		err = omap_request_dma(dev_id, dev_name,
c0fc18c5b   Russell King   [ARM] omap: fix l...
1233
  					callback, NULL, &channels[i]);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1234
1235
1236
1237
1238
1239
1240
1241
1242
  		if (err < 0) {
  			int j;
  			for (j = 0; j < i; j++)
  				omap_free_dma(channels[j]);
  			kfree(channels);
  			printk(KERN_ERR "omap_dma: Request failed %d
  ", err);
  			return err;
  		}
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
  		dma_chan[channels[i]].prev_linked_ch = -1;
  		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
  
  		/*
  		 * Allowing client drivers to set common parameters now,
  		 * so that later only relevant (src_start, dest_start
  		 * and element count) can be set
  		 */
  		omap_set_dma_params(channels[i], &params);
  	}
  
  	*chain_id = channels[0];
  	dma_linked_lch[*chain_id].linked_dmach_q = channels;
  	dma_linked_lch[*chain_id].chain_mode = chain_mode;
  	dma_linked_lch[*chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
  	dma_linked_lch[*chain_id].no_of_lchs_linked = no_of_chans;
  
  	for (i = 0; i < no_of_chans; i++)
  		dma_chan[channels[i]].chain_id = *chain_id;
  
  	/* Reset the Queue pointers */
  	OMAP_DMA_CHAIN_QINIT(*chain_id);
  
  	/* Set up the chain */
  	if (no_of_chans == 1)
  		create_dma_lch_chain(channels[0], channels[0]);
  	else {
  		for (i = 0; i < (no_of_chans - 1); i++)
  			create_dma_lch_chain(channels[i], channels[i + 1]);
  	}
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1273

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  	return 0;
  }
  EXPORT_SYMBOL(omap_request_dma_chain);
  
  /**
   * @brief omap_modify_dma_chain_param : Modify the chain's params - Modify the
   * params after setting it. Dont do this while dma is running!!
   *
   * @param chain_id - Chained logical channel id.
   * @param params
   *
   * @return - Success : 0
   * 	     Failure : -EINVAL
   */
  int omap_modify_dma_chain_params(int chain_id,
  				struct omap_dma_channel_params params)
  {
  	int *channels;
  	u32 i;
  
  	/* Check for input params */
  	if (unlikely((chain_id < 0
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1296
  			|| chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	/* Check if the chain exists */
  	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
  		printk(KERN_ERR "Chain doesn't exists
  ");
  		return -EINVAL;
  	}
  	channels = dma_linked_lch[chain_id].linked_dmach_q;
  
  	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
  		/*
  		 * Allowing client drivers to set common parameters now,
  		 * so that later only relevant (src_start, dest_start
  		 * and element count) can be set
  		 */
  		omap_set_dma_params(channels[i], &params);
  	}
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1318

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
  	return 0;
  }
  EXPORT_SYMBOL(omap_modify_dma_chain_params);
  
  /**
   * @brief omap_free_dma_chain - Free all the logical channels in a chain.
   *
   * @param chain_id
   *
   * @return - Success : 0
   * 	     Failure : -EINVAL
   */
  int omap_free_dma_chain(int chain_id)
  {
  	int *channels;
  	u32 i;
  
  	/* Check for input params */
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1337
  	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	/* Check if the chain exists */
  	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
  		printk(KERN_ERR "Chain doesn't exists
  ");
  		return -EINVAL;
  	}
  
  	channels = dma_linked_lch[chain_id].linked_dmach_q;
  	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
  		dma_chan[channels[i]].next_linked_ch = -1;
  		dma_chan[channels[i]].prev_linked_ch = -1;
  		dma_chan[channels[i]].chain_id = -1;
  		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
  		omap_free_dma(channels[i]);
  	}
  
  	kfree(channels);
  
  	dma_linked_lch[chain_id].linked_dmach_q = NULL;
  	dma_linked_lch[chain_id].chain_mode = -1;
  	dma_linked_lch[chain_id].chain_state = -1;
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1364

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
  	return (0);
  }
  EXPORT_SYMBOL(omap_free_dma_chain);
  
  /**
   * @brief omap_dma_chain_status - Check if the chain is in
   * active / inactive state.
   * @param chain_id
   *
   * @return - Success : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
   * 	     Failure : -EINVAL
   */
  int omap_dma_chain_status(int chain_id)
  {
  	/* Check for input params */
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1380
  	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	/* Check if the chain exists */
  	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
  		printk(KERN_ERR "Chain doesn't exists
  ");
  		return -EINVAL;
  	}
  	pr_debug("CHAINID=%d, qcnt=%d
  ", chain_id,
  			dma_linked_lch[chain_id].q_count);
  
  	if (OMAP_DMA_CHAIN_QEMPTY(chain_id))
  		return OMAP_DMA_CHAIN_INACTIVE;
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1398

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
  	return OMAP_DMA_CHAIN_ACTIVE;
  }
  EXPORT_SYMBOL(omap_dma_chain_status);
  
  /**
   * @brief omap_dma_chain_a_transfer - Get a free channel from a chain,
   * set the params and start the transfer.
   *
   * @param chain_id
   * @param src_start - buffer start address
   * @param dest_start - Dest address
   * @param elem_count
   * @param frame_count
   * @param callbk_data - channel callback parameter data.
   *
f4b6a7ef6   Anand Gadiyar   ARM: OMAP: Fix ch...
1414
   * @return  - Success : 0
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1415
1416
1417
1418
1419
1420
   * 	      Failure: -EINVAL/-EBUSY
   */
  int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
  			int elem_count, int frame_count, void *callbk_data)
  {
  	int *channels;
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1421
  	u32 l, lch;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1422
  	int start_dma = 0;
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1423
1424
1425
1426
  	/*
  	 * if buffer size is less than 1 then there is
  	 * no use of starting the chain
  	 */
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1427
1428
1429
1430
1431
1432
1433
1434
  	if (elem_count < 1) {
  		printk(KERN_ERR "Invalid buffer size
  ");
  		return -EINVAL;
  	}
  
  	/* Check for input params */
  	if (unlikely((chain_id < 0
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1435
  			|| chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	/* Check if the chain exists */
  	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
  		printk(KERN_ERR "Chain doesn't exist
  ");
  		return -EINVAL;
  	}
  
  	/* Check if all the channels in chain are in use */
  	if (OMAP_DMA_CHAIN_QFULL(chain_id))
  		return -EBUSY;
  
  	/* Frame count may be negative in case of indexed transfers */
  	channels = dma_linked_lch[chain_id].linked_dmach_q;
  
  	/* Get a free channel */
  	lch = channels[dma_linked_lch[chain_id].q_tail];
  
  	/* Store the callback data */
  	dma_chan[lch].data = callbk_data;
  
  	/* Increment the q_tail */
  	OMAP_DMA_CHAIN_INCQTAIL(chain_id);
  
  	/* Set the params to the free channel */
  	if (src_start != 0)
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1466
  		p->dma_write(src_start, CSSA, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1467
  	if (dest_start != 0)
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1468
  		p->dma_write(dest_start, CDSA, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1469
1470
  
  	/* Write the buffer size */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1471
1472
  	p->dma_write(elem_count, CEN, lch);
  	p->dma_write(frame_count, CFN, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1473

97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1474
1475
1476
1477
  	/*
  	 * If the chain is dynamically linked,
  	 * then we may have to start the chain if its not active
  	 */
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1478
  	if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) {
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1479
1480
1481
1482
  		/*
  		 * In Dynamic chain, if the chain is not started,
  		 * queue the channel
  		 */
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1483
1484
1485
1486
1487
1488
1489
1490
  		if (dma_linked_lch[chain_id].chain_state ==
  						DMA_CHAIN_NOTSTARTED) {
  			/* Enable the link in previous channel */
  			if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
  								DMA_CH_QUEUED)
  				enable_lnk(dma_chan[lch].prev_linked_ch);
  			dma_chan[lch].state = DMA_CH_QUEUED;
  		}
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1491
1492
1493
1494
  		/*
  		 * Chain is already started, make sure its active,
  		 * if not then start the chain
  		 */
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1495
1496
1497
1498
1499
1500
1501
1502
  		else {
  			start_dma = 1;
  
  			if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
  							DMA_CH_STARTED) {
  				enable_lnk(dma_chan[lch].prev_linked_ch);
  				dma_chan[lch].state = DMA_CH_QUEUED;
  				start_dma = 0;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1503
  				if (0 == ((1 << 7) & p->dma_read(
a4c537c7f   G, Manjunath Kondaiah   OMAP: DMA: Replac...
1504
  					CCR, dma_chan[lch].prev_linked_ch))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
  					disable_lnk(dma_chan[lch].
  						    prev_linked_ch);
  					pr_debug("
   prev ch is stopped
  ");
  					start_dma = 1;
  				}
  			}
  
  			else if (dma_chan[dma_chan[lch].prev_linked_ch].state
  							== DMA_CH_QUEUED) {
  				enable_lnk(dma_chan[lch].prev_linked_ch);
  				dma_chan[lch].state = DMA_CH_QUEUED;
  				start_dma = 0;
  			}
  			omap_enable_channel_irq(lch);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1521
  			l = p->dma_read(CCR, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1522

0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1523
1524
  			if ((0 == (l & (1 << 24))))
  				l &= ~(1 << 25);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1525
  			else
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1526
  				l |= (1 << 25);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1527
  			if (start_dma == 1) {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1528
1529
  				if (0 == (l & (1 << 7))) {
  					l |= (1 << 7);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1530
1531
1532
  					dma_chan[lch].state = DMA_CH_STARTED;
  					pr_debug("starting %d
  ", lch);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1533
  					p->dma_write(l, CCR, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1534
1535
1536
  				} else
  					start_dma = 0;
  			} else {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1537
  				if (0 == (l & (1 << 7)))
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1538
  					p->dma_write(l, CCR, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1539
1540
1541
1542
  			}
  			dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
  		}
  	}
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1543

f4b6a7ef6   Anand Gadiyar   ARM: OMAP: Fix ch...
1544
  	return 0;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
  }
  EXPORT_SYMBOL(omap_dma_chain_a_transfer);
  
  /**
   * @brief omap_start_dma_chain_transfers - Start the chain
   *
   * @param chain_id
   *
   * @return - Success : 0
   * 	     Failure : -EINVAL/-EBUSY
   */
  int omap_start_dma_chain_transfers(int chain_id)
  {
  	int *channels;
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1559
  	u32 l, i;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1560

4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1561
  	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	channels = dma_linked_lch[chain_id].linked_dmach_q;
  
  	if (dma_linked_lch[channels[0]].chain_state == DMA_CHAIN_STARTED) {
  		printk(KERN_ERR "Chain is already started
  ");
  		return -EBUSY;
  	}
  
  	if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_STATIC_CHAIN) {
  		for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked;
  									i++) {
  			enable_lnk(channels[i]);
  			omap_enable_channel_irq(channels[i]);
  		}
  	} else {
  		omap_enable_channel_irq(channels[0]);
  	}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1584
  	l = p->dma_read(CCR, channels[0]);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1585
  	l |= (1 << 7);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1586
1587
  	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
  	dma_chan[channels[0]].state = DMA_CH_STARTED;
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1588
1589
  	if ((0 == (l & (1 << 24))))
  		l &= ~(1 << 25);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1590
  	else
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1591
  		l |= (1 << 25);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1592
  	p->dma_write(l, CCR, channels[0]);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1593
1594
  
  	dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1595

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
  	return 0;
  }
  EXPORT_SYMBOL(omap_start_dma_chain_transfers);
  
  /**
   * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain.
   *
   * @param chain_id
   *
   * @return - Success : 0
   * 	     Failure : EINVAL
   */
  int omap_stop_dma_chain_transfers(int chain_id)
  {
  	int *channels;
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1611
  	u32 l, i;
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1612
  	u32 sys_cf = 0;
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1613
1614
  
  	/* Check for input params */
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1615
  	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	/* Check if the chain exists */
  	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
  		printk(KERN_ERR "Chain doesn't exists
  ");
  		return -EINVAL;
  	}
  	channels = dma_linked_lch[chain_id].linked_dmach_q;
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1628
  	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1629
  		sys_cf = p->dma_read(OCP_SYSCONFIG, 0);
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1630
1631
1632
  		l = sys_cf;
  		/* Middle mode reg set no Standby */
  		l &= ~((1 << 12)|(1 << 13));
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1633
  		p->dma_write(l, OCP_SYSCONFIG, 0);
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1634
  	}
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1635
1636
1637
1638
  
  	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
  
  		/* Stop the Channel transmission */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1639
  		l = p->dma_read(CCR, channels[i]);
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1640
  		l &= ~(1 << 7);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1641
  		p->dma_write(l, CCR, channels[i]);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
  
  		/* Disable the link in all the channels */
  		disable_lnk(channels[i]);
  		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
  
  	}
  	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
  
  	/* Reset the Queue pointers */
  	OMAP_DMA_CHAIN_QINIT(chain_id);
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1652
  	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1653
  		p->dma_write(sys_cf, OCP_SYSCONFIG, 0);
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1654

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
  	return 0;
  }
  EXPORT_SYMBOL(omap_stop_dma_chain_transfers);
  
  /* Get the index of the ongoing DMA in chain */
  /**
   * @brief omap_get_dma_chain_index - Get the element and frame index
   * of the ongoing DMA in chain
   *
   * @param chain_id
   * @param ei - Element index
   * @param fi - Frame index
   *
   * @return - Success : 0
   * 	     Failure : -EINVAL
   */
  int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
  {
  	int lch;
  	int *channels;
  
  	/* Check for input params */
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1677
  	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	/* Check if the chain exists */
  	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
  		printk(KERN_ERR "Chain doesn't exists
  ");
  		return -EINVAL;
  	}
  	if ((!ei) || (!fi))
  		return -EINVAL;
  
  	channels = dma_linked_lch[chain_id].linked_dmach_q;
  
  	/* Get the current channel */
  	lch = channels[dma_linked_lch[chain_id].q_head];
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1696
1697
  	*ei = p->dma_read(CCEN, lch);
  	*fi = p->dma_read(CCFN, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
  
  	return 0;
  }
  EXPORT_SYMBOL(omap_get_dma_chain_index);
  
  /**
   * @brief omap_get_dma_chain_dst_pos - Get the destination position of the
   * ongoing DMA in chain
   *
   * @param chain_id
   *
   * @return - Success : Destination position
   * 	     Failure : -EINVAL
   */
  int omap_get_dma_chain_dst_pos(int chain_id)
  {
  	int lch;
  	int *channels;
  
  	/* Check for input params */
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1718
  	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	/* Check if the chain exists */
  	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
  		printk(KERN_ERR "Chain doesn't exists
  ");
  		return -EINVAL;
  	}
  
  	channels = dma_linked_lch[chain_id].linked_dmach_q;
  
  	/* Get the current channel */
  	lch = channels[dma_linked_lch[chain_id].q_head];
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1735
  	return p->dma_read(CDAC, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
  }
  EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
  
  /**
   * @brief omap_get_dma_chain_src_pos - Get the source position
   * of the ongoing DMA in chain
   * @param chain_id
   *
   * @return - Success : Destination position
   * 	     Failure : -EINVAL
   */
  int omap_get_dma_chain_src_pos(int chain_id)
  {
  	int lch;
  	int *channels;
  
  	/* Check for input params */
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1753
  	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
  		printk(KERN_ERR "Invalid chain id
  ");
  		return -EINVAL;
  	}
  
  	/* Check if the chain exists */
  	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
  		printk(KERN_ERR "Chain doesn't exists
  ");
  		return -EINVAL;
  	}
  
  	channels = dma_linked_lch[chain_id].linked_dmach_q;
  
  	/* Get the current channel */
  	lch = channels[dma_linked_lch[chain_id].q_head];
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1770
  	return p->dma_read(CSAC, lch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1771
1772
  }
  EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1773
  #endif	/* ifndef CONFIG_ARCH_OMAP1 */
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1774

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1775
1776
1777
1778
1779
1780
  /*----------------------------------------------------------------------------*/
  
  #ifdef CONFIG_ARCH_OMAP1
  
  static int omap1_dma_handle_ch(int ch)
  {
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1781
  	u32 csr;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1782
1783
1784
1785
1786
  
  	if (enable_1510_mode && ch >= 6) {
  		csr = dma_chan[ch].saved_csr;
  		dma_chan[ch].saved_csr = 0;
  	} else
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1787
  		csr = p->dma_read(CSR, ch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
  	if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
  		dma_chan[ch + 6].saved_csr = csr >> 7;
  		csr &= 0x7f;
  	}
  	if ((csr & 0x3f) == 0)
  		return 0;
  	if (unlikely(dma_chan[ch].dev_id == -1)) {
  		printk(KERN_WARNING "Spurious interrupt from DMA channel "
  		       "%d (CSR %04x)
  ", ch, csr);
  		return 0;
  	}
7ff879dbc   Tony Lindgren   ARM: OMAP: Fix DM...
1800
  	if (unlikely(csr & OMAP1_DMA_TOUT_IRQ))
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
  		printk(KERN_WARNING "DMA timeout with device %d
  ",
  		       dma_chan[ch].dev_id);
  	if (unlikely(csr & OMAP_DMA_DROP_IRQ))
  		printk(KERN_WARNING "DMA synchronization event drop occurred "
  		       "with device %d
  ", dma_chan[ch].dev_id);
  	if (likely(csr & OMAP_DMA_BLOCK_IRQ))
  		dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
  	if (likely(dma_chan[ch].callback != NULL))
  		dma_chan[ch].callback(ch, csr, dma_chan[ch].data);
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1812

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1813
1814
  	return 1;
  }
0cd61b68c   Linus Torvalds   Initial blind fix...
1815
  static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
  {
  	int ch = ((int) dev_id) - 1;
  	int handled = 0;
  
  	for (;;) {
  		int handled_now = 0;
  
  		handled_now += omap1_dma_handle_ch(ch);
  		if (enable_1510_mode && dma_chan[ch + 6].saved_csr)
  			handled_now += omap1_dma_handle_ch(ch + 6);
  		if (!handled_now)
  			break;
  		handled += handled_now;
  	}
  
  	return handled ? IRQ_HANDLED : IRQ_NONE;
  }
  
  #else
  #define omap1_dma_irq_handler	NULL
  #endif
140455fa0   Tony Lindgren   omap2/3/4: Replac...
1837
  #ifdef CONFIG_ARCH_OMAP2PLUS
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1838
1839
1840
  
  static int omap2_dma_handle_ch(int ch)
  {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1841
  	u32 status = p->dma_read(CSR, ch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1842

3151369d7   Juha Yrjola   ARM: OMAP: Add DM...
1843
1844
  	if (!status) {
  		if (printk_ratelimit())
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
1845
1846
1847
  			printk(KERN_WARNING "Spurious DMA IRQ for lch %d
  ",
  				ch);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1848
  		p->dma_write(1 << ch, IRQSTATUS_L0, ch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1849
  		return 0;
3151369d7   Juha Yrjola   ARM: OMAP: Add DM...
1850
1851
1852
1853
1854
1855
  	}
  	if (unlikely(dma_chan[ch].dev_id == -1)) {
  		if (printk_ratelimit())
  			printk(KERN_WARNING "IRQ %04x for non-allocated DMA"
  					"channel %d
  ", status, ch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1856
  		return 0;
3151369d7   Juha Yrjola   ARM: OMAP: Add DM...
1857
  	}
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1858
1859
1860
1861
1862
  	if (unlikely(status & OMAP_DMA_DROP_IRQ))
  		printk(KERN_INFO
  		       "DMA synchronization event drop occurred with device "
  		       "%d
  ", dma_chan[ch].dev_id);
a50f18c70   Santosh Shilimkar   ARM: OMAP3: DMA: ...
1863
  	if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1864
1865
1866
  		printk(KERN_INFO "DMA transaction error with device %d
  ",
  		       dma_chan[ch].dev_id);
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1867
  		if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
a50f18c70   Santosh Shilimkar   ARM: OMAP3: DMA: ...
1868
  			u32 ccr;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1869
  			ccr = p->dma_read(CCR, ch);
a50f18c70   Santosh Shilimkar   ARM: OMAP3: DMA: ...
1870
  			ccr &= ~OMAP_DMA_CCR_EN;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1871
  			p->dma_write(ccr, CCR, ch);
a50f18c70   Santosh Shilimkar   ARM: OMAP3: DMA: ...
1872
1873
1874
  			dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
  		}
  	}
7ff879dbc   Tony Lindgren   ARM: OMAP: Fix DM...
1875
1876
1877
1878
1879
1880
1881
1882
  	if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ))
  		printk(KERN_INFO "DMA secure error with device %d
  ",
  		       dma_chan[ch].dev_id);
  	if (unlikely(status & OMAP2_DMA_MISALIGNED_ERR_IRQ))
  		printk(KERN_INFO "DMA misaligned error with device %d
  ",
  		       dma_chan[ch].dev_id);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1883

4fb699b40   Adrian Hunter   omap: DMA: clear ...
1884
  	p->dma_write(status, CSR, ch);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1885
  	p->dma_write(1 << ch, IRQSTATUS_L0, ch);
e860e6da9   Mathias Nyman   omap: dma: Add re...
1886
  	/* read back the register to flush the write */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1887
  	p->dma_read(IRQSTATUS_L0, ch);
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1888

f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1889
1890
1891
1892
  	/* If the ch is not chained then chain_id will be -1 */
  	if (dma_chan[ch].chain_id != -1) {
  		int chain_id = dma_chan[ch].chain_id;
  		dma_chan[ch].state = DMA_CH_NOTSTARTED;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1893
  		if (p->dma_read(CLNK_CTRL, ch) & (1 << 15))
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1894
1895
1896
1897
1898
1899
1900
1901
  			dma_chan[dma_chan[ch].next_linked_ch].state =
  							DMA_CH_STARTED;
  		if (dma_linked_lch[chain_id].chain_mode ==
  						OMAP_DMA_DYNAMIC_CHAIN)
  			disable_lnk(ch);
  
  		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
  			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1902
  		status = p->dma_read(CSR, ch);
4fb699b40   Adrian Hunter   omap: DMA: clear ...
1903
  		p->dma_write(status, CSR, ch);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1904
  	}
538528de0   Jarkko Nikula   ARM: OMAP: Pass l...
1905
1906
  	if (likely(dma_chan[ch].callback != NULL))
  		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
1907

1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1908
1909
1910
1911
  	return 0;
  }
  
  /* STATUS register count is from 1-32 while our is 0-31 */
0cd61b68c   Linus Torvalds   Initial blind fix...
1912
  static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1913
  {
52176e708   Santosh Shilimkar   ARM: OMAP: Dispat...
1914
  	u32 val, enable_reg;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1915
  	int i;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1916
  	val = p->dma_read(IRQSTATUS_L0, 0);
3151369d7   Juha Yrjola   ARM: OMAP: Add DM...
1917
1918
1919
1920
1921
1922
  	if (val == 0) {
  		if (printk_ratelimit())
  			printk(KERN_WARNING "Spurious DMA IRQ
  ");
  		return IRQ_HANDLED;
  	}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1923
  	enable_reg = p->dma_read(IRQENABLE_L0, 0);
52176e708   Santosh Shilimkar   ARM: OMAP: Dispat...
1924
  	val &= enable_reg; /* Dispatch only relevant interrupts */
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1925
  	for (i = 0; i < dma_lch_count && val != 0; i++) {
3151369d7   Juha Yrjola   ARM: OMAP: Add DM...
1926
1927
1928
  		if (val & 1)
  			omap2_dma_handle_ch(i);
  		val >>= 1;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1929
1930
1931
1932
1933
1934
1935
1936
  	}
  
  	return IRQ_HANDLED;
  }
  
  static struct irqaction omap24xx_dma_irq = {
  	.name = "DMA",
  	.handler = omap2_dma_irq_handler,
52e405eaa   Thomas Gleixner   [PATCH] ARM: fixu...
1937
  	.flags = IRQF_DISABLED
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
1938
1939
1940
1941
1942
1943
1944
  };
  
  #else
  static struct irqaction omap24xx_dma_irq;
  #endif
  
  /*----------------------------------------------------------------------------*/
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
1945

f2d118582   Tero Kristo   OMAP: PM: DMA con...
1946
1947
1948
  void omap_dma_global_context_save(void)
  {
  	omap_dma_global_context.dma_irqenable_l0 =
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1949
  		p->dma_read(IRQENABLE_L0, 0);
f2d118582   Tero Kristo   OMAP: PM: DMA con...
1950
  	omap_dma_global_context.dma_ocp_sysconfig =
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1951
1952
  		p->dma_read(OCP_SYSCONFIG, 0);
  	omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0);
f2d118582   Tero Kristo   OMAP: PM: DMA con...
1953
1954
1955
1956
  }
  
  void omap_dma_global_context_restore(void)
  {
bf07c9f2d   Aaro Koskinen   OMAP: PM: Clear D...
1957
  	int ch;
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1958
1959
  	p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
  	p->dma_write(omap_dma_global_context.dma_ocp_sysconfig,
a4c537c7f   G, Manjunath Kondaiah   OMAP: DMA: Replac...
1960
  		OCP_SYSCONFIG, 0);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1961
  	p->dma_write(omap_dma_global_context.dma_irqenable_l0,
a4c537c7f   G, Manjunath Kondaiah   OMAP: DMA: Replac...
1962
  		IRQENABLE_L0, 0);
f2d118582   Tero Kristo   OMAP: PM: DMA con...
1963

d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1964
  	if (IS_DMA_ERRATA(DMA_ROMCODE_BUG))
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1965
  		p->dma_write(0x3 , IRQSTATUS_L0, 0);
bf07c9f2d   Aaro Koskinen   OMAP: PM: Clear D...
1966
1967
1968
1969
  
  	for (ch = 0; ch < dma_chan_count; ch++)
  		if (dma_chan[ch].dev_id != -1)
  			omap_clear_dma(ch);
f2d118582   Tero Kristo   OMAP: PM: DMA con...
1970
  }
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1971
  static int __devinit omap_system_dma_probe(struct platform_device *pdev)
d3c9be2f4   G, Manjunath Kondaiah   OMAP: DMA: Introd...
1972
  {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
  	int ch, ret = 0;
  	int dma_irq;
  	char irq_name[4];
  	int irq_rel;
  
  	p = pdev->dev.platform_data;
  	if (!p) {
  		dev_err(&pdev->dev, "%s: System DMA initialized without"
  			"platform data
  ", __func__);
  		return -EINVAL;
0499bdeb1   Tony Lindgren   ARM: OMAP: DMA: R...
1984
  	}
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1985

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1986
1987
  	d			= p->dma_attr;
  	errata			= p->errata;
a4c537c7f   G, Manjunath Kondaiah   OMAP: DMA: Replac...
1988

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1989
  	if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels
2263f0222   Santosh Shilimkar   ARM: OMAP: Get av...
1990
  			&& (omap_dma_reserve_channels <= dma_lch_count))
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1991
  		d->lch_count	= omap_dma_reserve_channels;
2263f0222   Santosh Shilimkar   ARM: OMAP: Get av...
1992

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
1993
1994
1995
1996
  	dma_lch_count		= d->lch_count;
  	dma_chan_count		= dma_lch_count;
  	dma_chan		= d->chan;
  	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
1997
1998
1999
2000
2001
  
  	if (cpu_class_is_omap2()) {
  		dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
  						dma_lch_count, GFP_KERNEL);
  		if (!dma_linked_lch) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2002
2003
  			ret = -ENOMEM;
  			goto exit_dma_lch_fail;
4d96372e6   Tony Lindgren   ARM: OMAP: DMA: M...
2004
2005
  		}
  	}
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
2006
  	spin_lock_init(&dma_chan_lock);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
2007
  	for (ch = 0; ch < dma_chan_count; ch++) {
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
2008
  		omap_clear_dma(ch);
ada8d4a5e   Mika Westerberg   OMAP2/3/4: DMA: d...
2009
2010
  		if (cpu_class_is_omap2())
  			omap2_disable_irq_lch(ch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
2011
2012
2013
2014
2015
  		dma_chan[ch].dev_id = -1;
  		dma_chan[ch].next_lch = -1;
  
  		if (ch >= 6 && enable_1510_mode)
  			continue;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
2016
  		if (cpu_class_is_omap1()) {
97b7f7155   Tony Lindgren   ARM: OMAP: DMA: C...
2017
2018
2019
2020
  			/*
  			 * request_irq() doesn't like dev_id (ie. ch) being
  			 * zero, so we have to kludge around this.
  			 */
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
  			sprintf(&irq_name[0], "%d", ch);
  			dma_irq = platform_get_irq_byname(pdev, irq_name);
  
  			if (dma_irq < 0) {
  				ret = dma_irq;
  				goto exit_dma_irq_fail;
  			}
  
  			/* INT_DMA_LCD is handled in lcd_dma.c */
  			if (dma_irq == INT_DMA_LCD)
  				continue;
  
  			ret = request_irq(dma_irq,
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
2034
2035
  					omap1_dma_irq_handler, 0, "DMA",
  					(void *) (ch + 1));
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2036
2037
  			if (ret != 0)
  				goto exit_dma_irq_fail;
1a8bfa1eb   Tony Lindgren   [ARM] 3142/1: OMA...
2038
2039
  		}
  	}
44169075e   Santosh Shilimkar   ARM: OMAP4: Add m...
2040
  	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx())
f8151e5c3   Anand Gadiyar   ARM: OMAP: Add DM...
2041
2042
  		omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
  				DMA_DEFAULT_FIFO_DEPTH, 0);
44169075e   Santosh Shilimkar   ARM: OMAP4: Add m...
2043
  	if (cpu_class_is_omap2()) {
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
  		strcpy(irq_name, "0");
  		dma_irq = platform_get_irq_byname(pdev, irq_name);
  		if (dma_irq < 0) {
  			dev_err(&pdev->dev, "failed: request IRQ %d", dma_irq);
  			goto exit_dma_lch_fail;
  		}
  		ret = setup_irq(dma_irq, &omap24xx_dma_irq);
  		if (ret) {
  			dev_err(&pdev->dev, "set_up failed for IRQ %d"
  				"for DMA (error %d)
  ", dma_irq, ret);
  			goto exit_dma_lch_fail;
ba50ea7eb   Kalle Jokiniemi   OMAP3: PM: Fix se...
2056
  		}
aecedb94b   Kalle Jokiniemi   OMAP3: DMA: Enabl...
2057
  	}
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
  	/* reserve dma channels 0 and 1 in high security devices */
  	if (cpu_is_omap34xx() &&
  		(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
  		printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
  				"HS ROM code
  ");
  		dma_chan[0].dev_id = 0;
  		dma_chan[1].dev_id = 1;
  	}
  	p->show_dma_caps();
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
2068
  	return 0;
7e9bf8475   Tony Lindgren   omap: Use ioremap...
2069

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
  exit_dma_irq_fail:
  	dev_err(&pdev->dev, "unable to request IRQ %d"
  			"for DMA (error %d)
  ", dma_irq, ret);
  	for (irq_rel = 0; irq_rel < ch;	irq_rel++) {
  		dma_irq = platform_get_irq(pdev, irq_rel);
  		free_irq(dma_irq, (void *)(irq_rel + 1));
  	}
  
  exit_dma_lch_fail:
  	kfree(p);
  	kfree(d);
7e9bf8475   Tony Lindgren   omap: Use ioremap...
2082
  	kfree(dma_chan);
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2083
2084
  	return ret;
  }
7e9bf8475   Tony Lindgren   omap: Use ioremap...
2085

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2086
2087
2088
  static int __devexit omap_system_dma_remove(struct platform_device *pdev)
  {
  	int dma_irq;
7e9bf8475   Tony Lindgren   omap: Use ioremap...
2089

f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
  	if (cpu_class_is_omap2()) {
  		char irq_name[4];
  		strcpy(irq_name, "0");
  		dma_irq = platform_get_irq_byname(pdev, irq_name);
  		remove_irq(dma_irq, &omap24xx_dma_irq);
  	} else {
  		int irq_rel = 0;
  		for ( ; irq_rel < dma_chan_count; irq_rel++) {
  			dma_irq = platform_get_irq(pdev, irq_rel);
  			free_irq(dma_irq, (void *)(irq_rel + 1));
  		}
  	}
  	kfree(p);
  	kfree(d);
  	kfree(dma_chan);
  	return 0;
  }
  
  static struct platform_driver omap_system_dma_driver = {
  	.probe		= omap_system_dma_probe,
  	.remove		= omap_system_dma_remove,
  	.driver		= {
  		.name	= "omap_dma_system"
  	},
  };
  
  static int __init omap_system_dma_init(void)
  {
  	return platform_driver_register(&omap_system_dma_driver);
  }
  arch_initcall(omap_system_dma_init);
  
  static void __exit omap_system_dma_exit(void)
  {
  	platform_driver_unregister(&omap_system_dma_driver);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
2125
  }
f31cc9622   G, Manjunath Kondaiah   OMAP: DMA: Conver...
2126
2127
2128
2129
  MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("platform:" DRIVER_NAME);
  MODULE_AUTHOR("Texas Instruments Inc");
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
2130

2263f0222   Santosh Shilimkar   ARM: OMAP: Get av...
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
  /*
   * Reserve the omap SDMA channels using cmdline bootarg
   * "omap_dma_reserve_ch=". The valid range is 1 to 32
   */
  static int __init omap_dma_cmdline_reserve_ch(char *str)
  {
  	if (get_option(&str, &omap_dma_reserve_channels) != 1)
  		omap_dma_reserve_channels = 0;
  	return 1;
  }
  
  __setup("omap_dma_reserve_ch=", omap_dma_cmdline_reserve_ch);
5e1c5ff47   Tony Lindgren   [PATCH] ARM: 2812...
2143